@angular/animations 13.3.0 → 14.0.0-next.10

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 (41) hide show
  1. package/animations.d.ts +7 -2
  2. package/browser/browser.d.ts +18 -32
  3. package/browser/testing/testing.d.ts +9 -15
  4. package/esm2020/browser/src/dsl/animation.mjs +1 -1
  5. package/esm2020/browser/src/dsl/animation_ast.mjs +1 -1
  6. package/esm2020/browser/src/dsl/animation_ast_builder.mjs +57 -52
  7. package/esm2020/browser/src/dsl/animation_dsl_visitor.mjs +1 -1
  8. package/esm2020/browser/src/dsl/animation_timeline_builder.mjs +77 -87
  9. package/esm2020/browser/src/dsl/animation_timeline_instruction.mjs +1 -1
  10. package/esm2020/browser/src/dsl/animation_transition_factory.mjs +29 -18
  11. package/esm2020/browser/src/dsl/animation_transition_instruction.mjs +8 -1
  12. package/esm2020/browser/src/dsl/animation_trigger.mjs +9 -9
  13. package/esm2020/browser/src/dsl/style_normalization/web_animations_style_normalizer.mjs +33 -9
  14. package/esm2020/browser/src/private_export.mjs +2 -2
  15. package/esm2020/browser/src/render/animation_driver.mjs +4 -4
  16. package/esm2020/browser/src/render/shared.mjs +24 -29
  17. package/esm2020/browser/src/render/special_cased_styles.mjs +7 -16
  18. package/esm2020/browser/src/render/timeline_animation_engine.mjs +15 -15
  19. package/esm2020/browser/src/render/transition_animation_engine.mjs +68 -101
  20. package/esm2020/browser/src/render/web_animations/animatable_props_set.mjs +214 -0
  21. package/esm2020/browser/src/render/web_animations/web_animations_driver.mjs +17 -10
  22. package/esm2020/browser/src/render/web_animations/web_animations_player.mjs +16 -9
  23. package/esm2020/browser/src/util.mjs +40 -30
  24. package/esm2020/browser/src/warning_helpers.mjs +7 -2
  25. package/esm2020/browser/testing/src/mock_animation_driver.mjs +20 -14
  26. package/esm2020/src/animation_metadata.mjs +1 -1
  27. package/esm2020/src/animations.mjs +1 -1
  28. package/esm2020/src/version.mjs +1 -1
  29. package/fesm2015/animations.mjs +1 -1
  30. package/fesm2015/animations.mjs.map +1 -1
  31. package/fesm2015/browser/testing.mjs +856 -15
  32. package/fesm2015/browser/testing.mjs.map +1 -1
  33. package/fesm2015/browser.mjs +605 -371
  34. package/fesm2015/browser.mjs.map +1 -1
  35. package/fesm2020/animations.mjs +1 -1
  36. package/fesm2020/animations.mjs.map +1 -1
  37. package/fesm2020/browser/testing.mjs +856 -15
  38. package/fesm2020/browser/testing.mjs.map +1 -1
  39. package/fesm2020/browser.mjs +603 -371
  40. package/fesm2020/browser.mjs.map +1 -1
  41. package/package.json +3 -3
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license Angular v13.3.0
2
+ * @license Angular v14.0.0-next.10
3
3
  * (c) 2010-2022 Google LLC. https://angular.io/
4
4
  * License: MIT
5
5
  */
@@ -142,6 +142,220 @@ function transitionFailed(name, errors) {
142
142
  `@${name} has failed due to:\n ${errors.map(err => err.message).join('\n- ')}`);
143
143
  }
144
144
 
145
+ /**
146
+ * @license
147
+ * Copyright Google LLC All Rights Reserved.
148
+ *
149
+ * Use of this source code is governed by an MIT-style license that can be
150
+ * found in the LICENSE file at https://angular.io/license
151
+ */
152
+ /**
153
+ * Set of all animatable CSS properties
154
+ *
155
+ * @see https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_animated_properties
156
+ */
157
+ const ANIMATABLE_PROP_SET = new Set([
158
+ '-moz-outline-radius',
159
+ '-moz-outline-radius-bottomleft',
160
+ '-moz-outline-radius-bottomright',
161
+ '-moz-outline-radius-topleft',
162
+ '-moz-outline-radius-topright',
163
+ '-ms-grid-columns',
164
+ '-ms-grid-rows',
165
+ '-webkit-line-clamp',
166
+ '-webkit-text-fill-color',
167
+ '-webkit-text-stroke',
168
+ '-webkit-text-stroke-color',
169
+ 'accent-color',
170
+ 'all',
171
+ 'backdrop-filter',
172
+ 'background',
173
+ 'background-color',
174
+ 'background-position',
175
+ 'background-size',
176
+ 'block-size',
177
+ 'border',
178
+ 'border-block-end',
179
+ 'border-block-end-color',
180
+ 'border-block-end-width',
181
+ 'border-block-start',
182
+ 'border-block-start-color',
183
+ 'border-block-start-width',
184
+ 'border-bottom',
185
+ 'border-bottom-color',
186
+ 'border-bottom-left-radius',
187
+ 'border-bottom-right-radius',
188
+ 'border-bottom-width',
189
+ 'border-color',
190
+ 'border-end-end-radius',
191
+ 'border-end-start-radius',
192
+ 'border-image-outset',
193
+ 'border-image-slice',
194
+ 'border-image-width',
195
+ 'border-inline-end',
196
+ 'border-inline-end-color',
197
+ 'border-inline-end-width',
198
+ 'border-inline-start',
199
+ 'border-inline-start-color',
200
+ 'border-inline-start-width',
201
+ 'border-left',
202
+ 'border-left-color',
203
+ 'border-left-width',
204
+ 'border-radius',
205
+ 'border-right',
206
+ 'border-right-color',
207
+ 'border-right-width',
208
+ 'border-start-end-radius',
209
+ 'border-start-start-radius',
210
+ 'border-top',
211
+ 'border-top-color',
212
+ 'border-top-left-radius',
213
+ 'border-top-right-radius',
214
+ 'border-top-width',
215
+ 'border-width',
216
+ 'bottom',
217
+ 'box-shadow',
218
+ 'caret-color',
219
+ 'clip',
220
+ 'clip-path',
221
+ 'color',
222
+ 'column-count',
223
+ 'column-gap',
224
+ 'column-rule',
225
+ 'column-rule-color',
226
+ 'column-rule-width',
227
+ 'column-width',
228
+ 'columns',
229
+ 'filter',
230
+ 'flex',
231
+ 'flex-basis',
232
+ 'flex-grow',
233
+ 'flex-shrink',
234
+ 'font',
235
+ 'font-size',
236
+ 'font-size-adjust',
237
+ 'font-stretch',
238
+ 'font-variation-settings',
239
+ 'font-weight',
240
+ 'gap',
241
+ 'grid-column-gap',
242
+ 'grid-gap',
243
+ 'grid-row-gap',
244
+ 'grid-template-columns',
245
+ 'grid-template-rows',
246
+ 'height',
247
+ 'inline-size',
248
+ 'input-security',
249
+ 'inset',
250
+ 'inset-block',
251
+ 'inset-block-end',
252
+ 'inset-block-start',
253
+ 'inset-inline',
254
+ 'inset-inline-end',
255
+ 'inset-inline-start',
256
+ 'left',
257
+ 'letter-spacing',
258
+ 'line-clamp',
259
+ 'line-height',
260
+ 'margin',
261
+ 'margin-block-end',
262
+ 'margin-block-start',
263
+ 'margin-bottom',
264
+ 'margin-inline-end',
265
+ 'margin-inline-start',
266
+ 'margin-left',
267
+ 'margin-right',
268
+ 'margin-top',
269
+ 'mask',
270
+ 'mask-border',
271
+ 'mask-position',
272
+ 'mask-size',
273
+ 'max-block-size',
274
+ 'max-height',
275
+ 'max-inline-size',
276
+ 'max-lines',
277
+ 'max-width',
278
+ 'min-block-size',
279
+ 'min-height',
280
+ 'min-inline-size',
281
+ 'min-width',
282
+ 'object-position',
283
+ 'offset',
284
+ 'offset-anchor',
285
+ 'offset-distance',
286
+ 'offset-path',
287
+ 'offset-position',
288
+ 'offset-rotate',
289
+ 'opacity',
290
+ 'order',
291
+ 'outline',
292
+ 'outline-color',
293
+ 'outline-offset',
294
+ 'outline-width',
295
+ 'padding',
296
+ 'padding-block-end',
297
+ 'padding-block-start',
298
+ 'padding-bottom',
299
+ 'padding-inline-end',
300
+ 'padding-inline-start',
301
+ 'padding-left',
302
+ 'padding-right',
303
+ 'padding-top',
304
+ 'perspective',
305
+ 'perspective-origin',
306
+ 'right',
307
+ 'rotate',
308
+ 'row-gap',
309
+ 'scale',
310
+ 'scroll-margin',
311
+ 'scroll-margin-block',
312
+ 'scroll-margin-block-end',
313
+ 'scroll-margin-block-start',
314
+ 'scroll-margin-bottom',
315
+ 'scroll-margin-inline',
316
+ 'scroll-margin-inline-end',
317
+ 'scroll-margin-inline-start',
318
+ 'scroll-margin-left',
319
+ 'scroll-margin-right',
320
+ 'scroll-margin-top',
321
+ 'scroll-padding',
322
+ 'scroll-padding-block',
323
+ 'scroll-padding-block-end',
324
+ 'scroll-padding-block-start',
325
+ 'scroll-padding-bottom',
326
+ 'scroll-padding-inline',
327
+ 'scroll-padding-inline-end',
328
+ 'scroll-padding-inline-start',
329
+ 'scroll-padding-left',
330
+ 'scroll-padding-right',
331
+ 'scroll-padding-top',
332
+ 'scroll-snap-coordinate',
333
+ 'scroll-snap-destination',
334
+ 'scrollbar-color',
335
+ 'shape-image-threshold',
336
+ 'shape-margin',
337
+ 'shape-outside',
338
+ 'tab-size',
339
+ 'text-decoration',
340
+ 'text-decoration-color',
341
+ 'text-decoration-thickness',
342
+ 'text-emphasis',
343
+ 'text-emphasis-color',
344
+ 'text-indent',
345
+ 'text-shadow',
346
+ 'text-underline-offset',
347
+ 'top',
348
+ 'transform',
349
+ 'transform-origin',
350
+ 'translate',
351
+ 'vertical-align',
352
+ 'visibility',
353
+ 'width',
354
+ 'word-spacing',
355
+ 'z-index',
356
+ 'zoom',
357
+ ]);
358
+
145
359
  /**
146
360
  * @license
147
361
  * Copyright Google LLC All Rights Reserved.
@@ -170,26 +384,26 @@ function optimizeGroupPlayer(players) {
170
384
  return new ɵAnimationGroupPlayer(players);
171
385
  }
172
386
  }
173
- function normalizeKeyframes(driver, normalizer, element, keyframes, preStyles = {}, postStyles = {}) {
387
+ function normalizeKeyframes$1(driver, normalizer, element, keyframes, preStyles = new Map(), postStyles = new Map()) {
174
388
  const errors = [];
175
389
  const normalizedKeyframes = [];
176
390
  let previousOffset = -1;
177
391
  let previousKeyframe = null;
178
392
  keyframes.forEach(kf => {
179
- const offset = kf['offset'];
393
+ const offset = kf.get('offset');
180
394
  const isSameOffset = offset == previousOffset;
181
- const normalizedKeyframe = (isSameOffset && previousKeyframe) || {};
182
- Object.keys(kf).forEach(prop => {
395
+ const normalizedKeyframe = (isSameOffset && previousKeyframe) || new Map();
396
+ kf.forEach((val, prop) => {
183
397
  let normalizedProp = prop;
184
- let normalizedValue = kf[prop];
398
+ let normalizedValue = val;
185
399
  if (prop !== 'offset') {
186
400
  normalizedProp = normalizer.normalizePropertyName(normalizedProp, errors);
187
401
  switch (normalizedValue) {
188
402
  case ɵPRE_STYLE:
189
- normalizedValue = preStyles[prop];
403
+ normalizedValue = preStyles.get(prop);
190
404
  break;
191
405
  case AUTO_STYLE:
192
- normalizedValue = postStyles[prop];
406
+ normalizedValue = postStyles.get(prop);
193
407
  break;
194
408
  default:
195
409
  normalizedValue =
@@ -197,7 +411,7 @@ function normalizeKeyframes(driver, normalizer, element, keyframes, preStyles =
197
411
  break;
198
412
  }
199
413
  }
200
- normalizedKeyframe[normalizedProp] = normalizedValue;
414
+ normalizedKeyframe.set(normalizedProp, normalizedValue);
201
415
  });
202
416
  if (!isSameOffset) {
203
417
  normalizedKeyframes.push(normalizedKeyframe);
@@ -236,26 +450,17 @@ function copyAnimationEvent(e, phaseName, player) {
236
450
  function makeAnimationEvent(element, triggerName, fromState, toState, phaseName = '', totalTime = 0, disabled) {
237
451
  return { element, triggerName, fromState, toState, phaseName, totalTime, disabled: !!disabled };
238
452
  }
239
- function getOrSetAsInMap(map, key, defaultValue) {
240
- let value;
241
- if (map instanceof Map) {
242
- value = map.get(key);
243
- if (!value) {
244
- map.set(key, value = defaultValue);
245
- }
246
- }
247
- else {
248
- value = map[key];
249
- if (!value) {
250
- value = map[key] = defaultValue;
251
- }
453
+ function getOrSetDefaultValue(map, key, defaultValue) {
454
+ let value = map.get(key);
455
+ if (!value) {
456
+ map.set(key, value = defaultValue);
252
457
  }
253
458
  return value;
254
459
  }
255
460
  function parseTimelineCommand(command) {
256
461
  const separatorPos = command.indexOf(':');
257
462
  const id = command.substring(1, separatorPos);
258
- const action = command.substr(separatorPos + 1);
463
+ const action = command.slice(separatorPos + 1);
259
464
  return [id, action];
260
465
  }
261
466
  let _contains = (elm1, elm2) => false;
@@ -315,12 +520,15 @@ function validateStyleProperty(prop) {
315
520
  if (_CACHED_BODY.style && !containsVendorPrefix(prop)) {
316
521
  result = prop in _CACHED_BODY.style;
317
522
  if (!result && _IS_WEBKIT) {
318
- const camelProp = 'Webkit' + prop.charAt(0).toUpperCase() + prop.substr(1);
523
+ const camelProp = 'Webkit' + prop.charAt(0).toUpperCase() + prop.slice(1);
319
524
  result = camelProp in _CACHED_BODY.style;
320
525
  }
321
526
  }
322
527
  return result;
323
528
  }
529
+ function validateWebAnimatableStyleProperty(prop) {
530
+ return ANIMATABLE_PROP_SET.has(prop);
531
+ }
324
532
  function getBodyNode() {
325
533
  if (typeof document != 'undefined') {
326
534
  return document.body;
@@ -329,13 +537,13 @@ function getBodyNode() {
329
537
  }
330
538
  const containsElement = _contains;
331
539
  const invokeQuery = _query;
332
- function hypenatePropsObject(object) {
333
- const newObj = {};
334
- Object.keys(object).forEach(prop => {
540
+ function hypenatePropsKeys(original) {
541
+ const newMap = new Map();
542
+ original.forEach((val, prop) => {
335
543
  const newProp = prop.replace(/([a-z])([A-Z])/g, '$1-$2');
336
- newObj[newProp] = object[prop];
544
+ newMap.set(newProp, val);
337
545
  });
338
- return newObj;
546
+ return newMap;
339
547
  }
340
548
 
341
549
  /**
@@ -372,9 +580,9 @@ class NoopAnimationDriver {
372
580
  return new NoopAnimationPlayer(duration, delay);
373
581
  }
374
582
  }
375
- NoopAnimationDriver.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.0", ngImport: i0, type: NoopAnimationDriver, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
376
- NoopAnimationDriver.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "13.3.0", ngImport: i0, type: NoopAnimationDriver });
377
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.0", ngImport: i0, type: NoopAnimationDriver, decorators: [{
583
+ NoopAnimationDriver.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.10", ngImport: i0, type: NoopAnimationDriver, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
584
+ NoopAnimationDriver.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.0-next.10", ngImport: i0, type: NoopAnimationDriver });
585
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.10", ngImport: i0, type: NoopAnimationDriver, decorators: [{
378
586
  type: Injectable
379
587
  }] });
380
588
  /**
@@ -468,27 +676,41 @@ function copyObj(obj, destination = {}) {
468
676
  });
469
677
  return destination;
470
678
  }
679
+ function convertToMap(obj) {
680
+ const styleMap = new Map();
681
+ Object.keys(obj).forEach(prop => {
682
+ const val = obj[prop];
683
+ styleMap.set(prop, val);
684
+ });
685
+ return styleMap;
686
+ }
687
+ function normalizeKeyframes(keyframes) {
688
+ if (!keyframes.length) {
689
+ return [];
690
+ }
691
+ if (keyframes[0] instanceof Map) {
692
+ return keyframes;
693
+ }
694
+ return keyframes.map(kf => convertToMap(kf));
695
+ }
471
696
  function normalizeStyles(styles) {
472
- const normalizedStyles = {};
697
+ const normalizedStyles = new Map();
473
698
  if (Array.isArray(styles)) {
474
- styles.forEach(data => copyStyles(data, false, normalizedStyles));
699
+ styles.forEach(data => copyStyles(data, normalizedStyles));
475
700
  }
476
701
  else {
477
- copyStyles(styles, false, normalizedStyles);
702
+ copyStyles(styles, normalizedStyles);
478
703
  }
479
704
  return normalizedStyles;
480
705
  }
481
- function copyStyles(styles, readPrototype, destination = {}) {
482
- if (readPrototype) {
483
- // we make use of a for-in loop so that the
484
- // prototypically inherited properties are
485
- // revealed from the backFill map
486
- for (let prop in styles) {
487
- destination[prop] = styles[prop];
706
+ function copyStyles(styles, destination = new Map(), backfill) {
707
+ if (backfill) {
708
+ for (let [prop, val] of backfill) {
709
+ destination.set(prop, val);
488
710
  }
489
711
  }
490
- else {
491
- copyObj(styles, destination);
712
+ for (let [prop, val] of styles) {
713
+ destination.set(prop, val);
492
714
  }
493
715
  return destination;
494
716
  }
@@ -524,12 +746,12 @@ function writeStyleAttribute(element) {
524
746
  }
525
747
  function setStyles(element, styles, formerStyles) {
526
748
  if (element['style']) {
527
- Object.keys(styles).forEach(prop => {
749
+ styles.forEach((val, prop) => {
528
750
  const camelProp = dashCaseToCamelCase(prop);
529
- if (formerStyles && !formerStyles.hasOwnProperty(prop)) {
530
- formerStyles[prop] = element.style[camelProp];
751
+ if (formerStyles && !formerStyles.has(prop)) {
752
+ formerStyles.set(prop, element.style[camelProp]);
531
753
  }
532
- element.style[camelProp] = styles[prop];
754
+ element.style[camelProp] = val;
533
755
  });
534
756
  // On the server set the 'style' attribute since it's not automatically reflected.
535
757
  if (isNode()) {
@@ -539,7 +761,7 @@ function setStyles(element, styles, formerStyles) {
539
761
  }
540
762
  function eraseStyles(element, styles) {
541
763
  if (element['style']) {
542
- Object.keys(styles).forEach(prop => {
764
+ styles.forEach((_, prop) => {
543
765
  const camelProp = dashCaseToCamelCase(prop);
544
766
  element.style[camelProp] = '';
545
767
  });
@@ -585,7 +807,7 @@ function interpolateParams(value, params, errors) {
585
807
  const str = original.replace(PARAM_REGEX, (_, varName) => {
586
808
  let localVal = params[varName];
587
809
  // this means that the value was never overridden by the data passed in by the user
588
- if (!params.hasOwnProperty(varName)) {
810
+ if (localVal == null) {
589
811
  errors.push(invalidParamValue(varName));
590
812
  localVal = '';
591
813
  }
@@ -614,23 +836,19 @@ function allowPreviousPlayerStylesMerge(duration, delay) {
614
836
  return duration === 0 || delay === 0;
615
837
  }
616
838
  function balancePreviousStylesIntoKeyframes(element, keyframes, previousStyles) {
617
- const previousStyleProps = Object.keys(previousStyles);
618
- if (previousStyleProps.length && keyframes.length) {
839
+ if (previousStyles.size && keyframes.length) {
619
840
  let startingKeyframe = keyframes[0];
620
841
  let missingStyleProps = [];
621
- previousStyleProps.forEach(prop => {
622
- if (!startingKeyframe.hasOwnProperty(prop)) {
842
+ previousStyles.forEach((val, prop) => {
843
+ if (!startingKeyframe.has(prop)) {
623
844
  missingStyleProps.push(prop);
624
845
  }
625
- startingKeyframe[prop] = previousStyles[prop];
846
+ startingKeyframe.set(prop, val);
626
847
  });
627
848
  if (missingStyleProps.length) {
628
- // tslint:disable-next-line
629
- for (var i = 1; i < keyframes.length; i++) {
849
+ for (let i = 1; i < keyframes.length; i++) {
630
850
  let kf = keyframes[i];
631
- missingStyleProps.forEach(function (prop) {
632
- kf[prop] = computeStyle(element, prop);
633
- });
851
+ missingStyleProps.forEach(prop => kf.set(prop, computeStyle(element, prop)));
634
852
  }
635
853
  }
636
854
  }
@@ -701,7 +919,12 @@ function triggerParsingWarnings(name, warnings) {
701
919
  }
702
920
  function pushUnrecognizedPropertiesWarning(warnings, props) {
703
921
  if (ngDevMode && props.length) {
704
- warnings.push(`The provided CSS properties are not recognized properties supported for animations: ${props.join(', ')}`);
922
+ warnings.push(`The following provided properties are not recognized: ${props.join(', ')}`);
923
+ }
924
+ }
925
+ function pushNonAnimatablePropertiesWarning(warnings, props) {
926
+ if (props.length) {
927
+ warnings.push(`The following provided properties are not animatable: ${props.join(', ')}\n (see: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_animated_properties)`);
705
928
  }
706
929
  }
707
930
 
@@ -843,12 +1066,16 @@ class AnimationAstBuilderVisitor {
843
1066
  if (context.unsupportedCSSPropertiesFound.size) {
844
1067
  pushUnrecognizedPropertiesWarning(warnings, [...context.unsupportedCSSPropertiesFound.keys()]);
845
1068
  }
1069
+ if ((typeof ngDevMode === 'undefined' || ngDevMode) &&
1070
+ context.nonAnimatableCSSPropertiesFound.size) {
1071
+ pushNonAnimatablePropertiesWarning(warnings, [...context.nonAnimatableCSSPropertiesFound.keys()]);
1072
+ }
846
1073
  return ast;
847
1074
  }
848
1075
  _resetContextStyleTimingState(context) {
849
1076
  context.currentQuerySelector = ROOT_SELECTOR;
850
- context.collectedStyles = {};
851
- context.collectedStyles[ROOT_SELECTOR] = {};
1077
+ context.collectedStyles = new Map();
1078
+ context.collectedStyles.set(ROOT_SELECTOR, new Map());
852
1079
  context.currentTime = 0;
853
1080
  }
854
1081
  visitTrigger(metadata, context) {
@@ -896,11 +1123,10 @@ class AnimationAstBuilderVisitor {
896
1123
  if (styleAst.containsDynamicStyles) {
897
1124
  const missingSubs = new Set();
898
1125
  const params = astParams || {};
899
- styleAst.styles.forEach(value => {
900
- if (isObject(value)) {
901
- const stylesObj = value;
902
- Object.keys(stylesObj).forEach(prop => {
903
- extractStyleParams(stylesObj[prop]).forEach(sub => {
1126
+ styleAst.styles.forEach(style => {
1127
+ if (style instanceof Map) {
1128
+ style.forEach(value => {
1129
+ extractStyleParams(value).forEach(sub => {
904
1130
  if (!params.hasOwnProperty(sub)) {
905
1131
  missingSubs.add(sub);
906
1132
  }
@@ -996,37 +1222,30 @@ class AnimationAstBuilderVisitor {
996
1222
  }
997
1223
  _makeStyleAst(metadata, context) {
998
1224
  const styles = [];
999
- if (Array.isArray(metadata.styles)) {
1000
- metadata.styles.forEach(styleTuple => {
1001
- if (typeof styleTuple == 'string') {
1002
- if (styleTuple == AUTO_STYLE) {
1003
- styles.push(styleTuple);
1004
- }
1005
- else {
1006
- context.errors.push(invalidStyleValue(styleTuple));
1007
- }
1225
+ const metadataStyles = Array.isArray(metadata.styles) ? metadata.styles : [metadata.styles];
1226
+ for (let styleTuple of metadataStyles) {
1227
+ if (typeof styleTuple === 'string') {
1228
+ if (styleTuple === AUTO_STYLE) {
1229
+ styles.push(styleTuple);
1008
1230
  }
1009
1231
  else {
1010
- styles.push(styleTuple);
1232
+ context.errors.push(invalidStyleValue(styleTuple));
1011
1233
  }
1012
- });
1013
- }
1014
- else {
1015
- styles.push(metadata.styles);
1234
+ }
1235
+ else {
1236
+ styles.push(convertToMap(styleTuple));
1237
+ }
1016
1238
  }
1017
1239
  let containsDynamicStyles = false;
1018
1240
  let collectedEasing = null;
1019
1241
  styles.forEach(styleData => {
1020
- if (isObject(styleData)) {
1021
- const styleMap = styleData;
1022
- const easing = styleMap['easing'];
1023
- if (easing) {
1024
- collectedEasing = easing;
1025
- delete styleMap['easing'];
1242
+ if (styleData instanceof Map) {
1243
+ if (styleData.has('easing')) {
1244
+ collectedEasing = styleData.get('easing');
1245
+ styleData.delete('easing');
1026
1246
  }
1027
1247
  if (!containsDynamicStyles) {
1028
- for (let prop in styleMap) {
1029
- const value = styleMap[prop];
1248
+ for (let value of styleData.values()) {
1030
1249
  if (value.toString().indexOf(SUBSTITUTION_EXPR_START) >= 0) {
1031
1250
  containsDynamicStyles = true;
1032
1251
  break;
@@ -1052,16 +1271,27 @@ class AnimationAstBuilderVisitor {
1052
1271
  startTime -= timings.duration + timings.delay;
1053
1272
  }
1054
1273
  ast.styles.forEach(tuple => {
1055
- if (typeof tuple == 'string')
1274
+ if (typeof tuple === 'string')
1056
1275
  return;
1057
- Object.keys(tuple).forEach(prop => {
1276
+ tuple.forEach((value, prop) => {
1058
1277
  if (!this._driver.validateStyleProperty(prop)) {
1059
- delete tuple[prop];
1278
+ tuple.delete(prop);
1060
1279
  context.unsupportedCSSPropertiesFound.add(prop);
1061
1280
  return;
1062
1281
  }
1063
- const collectedStyles = context.collectedStyles[context.currentQuerySelector];
1064
- const collectedEntry = collectedStyles[prop];
1282
+ if ((typeof ngDevMode === 'undefined' || ngDevMode) &&
1283
+ this._driver.validateAnimatableStyleProperty) {
1284
+ if (!this._driver.validateAnimatableStyleProperty(prop)) {
1285
+ context.nonAnimatableCSSPropertiesFound.add(prop);
1286
+ // note: non animatable properties are not removed for the tuple just in case they are
1287
+ // categorized as non animatable but can actually be animated
1288
+ return;
1289
+ }
1290
+ }
1291
+ // This is guaranteed to have a defined Map at this querySelector location making it
1292
+ // safe to add the assertion here. It is set as a default empty map in prior methods.
1293
+ const collectedStyles = context.collectedStyles.get(context.currentQuerySelector);
1294
+ const collectedEntry = collectedStyles.get(prop);
1065
1295
  let updateCollectedStyle = true;
1066
1296
  if (collectedEntry) {
1067
1297
  if (startTime != endTime && startTime >= collectedEntry.startTime &&
@@ -1075,10 +1305,10 @@ class AnimationAstBuilderVisitor {
1075
1305
  startTime = collectedEntry.startTime;
1076
1306
  }
1077
1307
  if (updateCollectedStyle) {
1078
- collectedStyles[prop] = { startTime, endTime };
1308
+ collectedStyles.set(prop, { startTime, endTime });
1079
1309
  }
1080
1310
  if (context.options) {
1081
- validateStyleParams(tuple[prop], context.options, context.errors);
1311
+ validateStyleParams(value, context.options, context.errors);
1082
1312
  }
1083
1313
  });
1084
1314
  });
@@ -1167,7 +1397,7 @@ class AnimationAstBuilderVisitor {
1167
1397
  const [selector, includeSelf] = normalizeSelector(metadata.selector);
1168
1398
  context.currentQuerySelector =
1169
1399
  parentSelector.length ? (parentSelector + ' ' + selector) : selector;
1170
- getOrSetAsInMap(context.collectedStyles, context.currentQuerySelector, {});
1400
+ getOrSetDefaultValue(context.collectedStyles, context.currentQuerySelector, new Map());
1171
1401
  const animation = visitDslNode(this, normalizeAnimationEntry(metadata.animation), context);
1172
1402
  context.currentQuery = null;
1173
1403
  context.currentQuerySelector = parentSelector;
@@ -1205,7 +1435,7 @@ function normalizeSelector(selector) {
1205
1435
  // Note: the :enter and :leave aren't normalized here since those
1206
1436
  // selectors are filled in at runtime during timeline building
1207
1437
  selector = selector.replace(/@\*/g, NG_TRIGGER_SELECTOR)
1208
- .replace(/@\w+/g, match => NG_TRIGGER_SELECTOR + '-' + match.substr(1))
1438
+ .replace(/@\w+/g, match => NG_TRIGGER_SELECTOR + '-' + match.slice(1))
1209
1439
  .replace(/:animating/g, NG_ANIMATING_SELECTOR);
1210
1440
  return [selector, hasAmpersand];
1211
1441
  }
@@ -1222,9 +1452,10 @@ class AnimationAstBuilderContext {
1222
1452
  this.currentQuerySelector = null;
1223
1453
  this.currentAnimateTimings = null;
1224
1454
  this.currentTime = 0;
1225
- this.collectedStyles = {};
1455
+ this.collectedStyles = new Map();
1226
1456
  this.options = null;
1227
1457
  this.unsupportedCSSPropertiesFound = new Set();
1458
+ this.nonAnimatableCSSPropertiesFound = new Set();
1228
1459
  }
1229
1460
  }
1230
1461
  function consumeOffset(styles) {
@@ -1233,23 +1464,20 @@ function consumeOffset(styles) {
1233
1464
  let offset = null;
1234
1465
  if (Array.isArray(styles)) {
1235
1466
  styles.forEach(styleTuple => {
1236
- if (isObject(styleTuple) && styleTuple.hasOwnProperty('offset')) {
1467
+ if (styleTuple instanceof Map && styleTuple.has('offset')) {
1237
1468
  const obj = styleTuple;
1238
- offset = parseFloat(obj['offset']);
1239
- delete obj['offset'];
1469
+ offset = parseFloat(obj.get('offset'));
1470
+ obj.delete('offset');
1240
1471
  }
1241
1472
  });
1242
1473
  }
1243
- else if (isObject(styles) && styles.hasOwnProperty('offset')) {
1474
+ else if (styles instanceof Map && styles.has('offset')) {
1244
1475
  const obj = styles;
1245
- offset = parseFloat(obj['offset']);
1246
- delete obj['offset'];
1476
+ offset = parseFloat(obj.get('offset'));
1477
+ obj.delete('offset');
1247
1478
  }
1248
1479
  return offset;
1249
1480
  }
1250
- function isObject(value) {
1251
- return !Array.isArray(value) && typeof value == 'object';
1252
- }
1253
1481
  function constructTimingAst(value, errors) {
1254
1482
  let timings = null;
1255
1483
  if (value.hasOwnProperty('duration')) {
@@ -1357,7 +1585,7 @@ const LEAVE_TOKEN_REGEX = new RegExp(LEAVE_TOKEN, 'g');
1357
1585
  * ```
1358
1586
  *
1359
1587
  * For this operation to cover the combination of animation verbs (style, animate, group, etc...) a
1360
- * combination of prototypical inheritance, AST traversal and merge-sort-like algorithms are used.
1588
+ * combination of AST traversal and merge-sort-like algorithms are used.
1361
1589
  *
1362
1590
  * [AST Traversal]
1363
1591
  * Each of the animation verbs, when executed, will return an string-map object representing what
@@ -1403,23 +1631,18 @@ const LEAVE_TOKEN_REGEX = new RegExp(LEAVE_TOKEN, 'g');
1403
1631
  * from all previous animation steps. Therefore when a keyframe is created it would also be missing
1404
1632
  * from all previous keyframes up until where it is first used. For the timeline keyframe generation
1405
1633
  * to properly fill in the style it will place the previous value (the value from the parent
1406
- * timeline) or a default value of `*` into the backFill object. Given that each of the keyframe
1407
- * styles is an object that prototypically inherits from the backFill object, this means that if a
1408
- * value is added into the backFill then it will automatically propagate any missing values to all
1409
- * keyframes. Therefore the missing `height` value will be properly filled into the already
1410
- * processed keyframes.
1634
+ * timeline) or a default value of `*` into the backFill map. The `copyStyles` method in util.ts
1635
+ * handles propagating that backfill map to the styles object.
1411
1636
  *
1412
1637
  * When a sub-timeline is created it will have its own backFill property. This is done so that
1413
1638
  * styles present within the sub-timeline do not accidentally seep into the previous/future timeline
1414
1639
  * keyframes
1415
1640
  *
1416
- * (For prototypically-inherited contents to be detected a `for(i in obj)` loop must be used.)
1417
- *
1418
1641
  * [Validation]
1419
1642
  * The code in this file is not responsible for validation. That functionality happens with within
1420
1643
  * the `AnimationValidatorVisitor` code.
1421
1644
  */
1422
- function buildAnimationTimelines(driver, rootElement, ast, enterClassName, leaveClassName, startingStyles = {}, finalStyles = {}, options, subInstructions, errors = []) {
1645
+ function buildAnimationTimelines(driver, rootElement, ast, enterClassName, leaveClassName, startingStyles = new Map(), finalStyles = new Map(), options, subInstructions, errors = []) {
1423
1646
  return new AnimationTimelineBuilderVisitor().buildKeyframes(driver, rootElement, ast, enterClassName, leaveClassName, startingStyles, finalStyles, options, subInstructions, errors);
1424
1647
  }
1425
1648
  class AnimationTimelineBuilderVisitor {
@@ -1427,15 +1650,17 @@ class AnimationTimelineBuilderVisitor {
1427
1650
  subInstructions = subInstructions || new ElementInstructionMap();
1428
1651
  const context = new AnimationTimelineContext(driver, rootElement, subInstructions, enterClassName, leaveClassName, errors, []);
1429
1652
  context.options = options;
1653
+ const delay = options.delay ? resolveTimingValue(options.delay) : 0;
1654
+ context.currentTimeline.delayNextStep(delay);
1430
1655
  context.currentTimeline.setStyles([startingStyles], null, context.errors, options);
1431
1656
  visitDslNode(this, ast, context);
1432
1657
  // this checks to see if an actual animation happened
1433
1658
  const timelines = context.timelines.filter(timeline => timeline.containsAnimation());
1434
- if (Object.keys(finalStyles).length) {
1435
- // note: we just want to apply the final styles for the rootElement, so we do not
1436
- // just apply the styles to the last timeline but the last timeline which
1437
- // element is the root one (basically `*`-styles are replaced with the actual
1438
- // state style values only for the root element)
1659
+ // note: we just want to apply the final styles for the rootElement, so we do not
1660
+ // just apply the styles to the last timeline but the last timeline which
1661
+ // element is the root one (basically `*`-styles are replaced with the actual
1662
+ // state style values only for the root element)
1663
+ if (timelines.length && finalStyles.size) {
1439
1664
  let lastRootTimeline;
1440
1665
  for (let i = timelines.length - 1; i >= 0; i--) {
1441
1666
  const timeline = timelines[i];
@@ -1448,8 +1673,9 @@ class AnimationTimelineBuilderVisitor {
1448
1673
  lastRootTimeline.setStyles([finalStyles], null, context.errors, options);
1449
1674
  }
1450
1675
  }
1451
- return timelines.length ? timelines.map(timeline => timeline.buildKeyframes()) :
1452
- [createTimelineInstruction(rootElement, [], [], [], 0, 0, '', false)];
1676
+ return timelines.length ?
1677
+ timelines.map(timeline => timeline.buildKeyframes()) :
1678
+ [createTimelineInstruction(rootElement, [], [], [], 0, delay, '', false)];
1453
1679
  }
1454
1680
  visitTrigger(ast, context) {
1455
1681
  // these values are not visited in this AST
@@ -1585,7 +1811,7 @@ class AnimationTimelineBuilderVisitor {
1585
1811
  const timings = context.currentAnimateTimings;
1586
1812
  // this is a special case for when a style() call
1587
1813
  // directly follows an animate() call (but not inside of an animate() call)
1588
- if (!timings && timeline.getCurrentStyleProperties().length) {
1814
+ if (!timings && timeline.hasCurrentStyleProperties()) {
1589
1815
  timeline.forwardFrame();
1590
1816
  }
1591
1817
  const easing = (timings && timings.easing) || ast.easing;
@@ -1626,7 +1852,7 @@ class AnimationTimelineBuilderVisitor {
1626
1852
  const delay = options.delay ? resolveTimingValue(options.delay) : 0;
1627
1853
  if (delay &&
1628
1854
  (context.previousNode.type === 6 /* Style */ ||
1629
- (startTime == 0 && context.currentTimeline.getCurrentStyleProperties().length))) {
1855
+ (startTime == 0 && context.currentTimeline.hasCurrentStyleProperties()))) {
1630
1856
  context.currentTimeline.snapshotCurrentStyles();
1631
1857
  context.previousNode = DEFAULT_NOOP_PREVIOUS_NODE;
1632
1858
  }
@@ -1820,17 +2046,17 @@ class TimelineBuilder {
1820
2046
  this.startTime = startTime;
1821
2047
  this._elementTimelineStylesLookup = _elementTimelineStylesLookup;
1822
2048
  this.duration = 0;
1823
- this._previousKeyframe = {};
1824
- this._currentKeyframe = {};
2049
+ this._previousKeyframe = new Map();
2050
+ this._currentKeyframe = new Map();
1825
2051
  this._keyframes = new Map();
1826
- this._styleSummary = {};
1827
- this._pendingStyles = {};
1828
- this._backFill = {};
2052
+ this._styleSummary = new Map();
2053
+ this._localTimelineStyles = new Map();
2054
+ this._pendingStyles = new Map();
2055
+ this._backFill = new Map();
1829
2056
  this._currentEmptyStepKeyframe = null;
1830
2057
  if (!this._elementTimelineStylesLookup) {
1831
2058
  this._elementTimelineStylesLookup = new Map();
1832
2059
  }
1833
- this._localTimelineStyles = Object.create(this._backFill, {});
1834
2060
  this._globalTimelineStyles = this._elementTimelineStylesLookup.get(element);
1835
2061
  if (!this._globalTimelineStyles) {
1836
2062
  this._globalTimelineStyles = this._localTimelineStyles;
@@ -1843,13 +2069,13 @@ class TimelineBuilder {
1843
2069
  case 0:
1844
2070
  return false;
1845
2071
  case 1:
1846
- return this.getCurrentStyleProperties().length > 0;
2072
+ return this.hasCurrentStyleProperties();
1847
2073
  default:
1848
2074
  return true;
1849
2075
  }
1850
2076
  }
1851
- getCurrentStyleProperties() {
1852
- return Object.keys(this._currentKeyframe);
2077
+ hasCurrentStyleProperties() {
2078
+ return this._currentKeyframe.size > 0;
1853
2079
  }
1854
2080
  get currentTime() {
1855
2081
  return this.startTime + this.duration;
@@ -1859,7 +2085,7 @@ class TimelineBuilder {
1859
2085
  // and that style() step is the very first style() value in the animation
1860
2086
  // then we need to make a copy of the keyframe [0, copy, 1] so that the delay
1861
2087
  // properly applies the style() values to work with the stagger...
1862
- const hasPreStyleStep = this._keyframes.size == 1 && Object.keys(this._pendingStyles).length;
2088
+ const hasPreStyleStep = this._keyframes.size === 1 && this._pendingStyles.size;
1863
2089
  if (this.duration || hasPreStyleStep) {
1864
2090
  this.forwardTime(this.currentTime + delay);
1865
2091
  if (hasPreStyleStep) {
@@ -1880,7 +2106,7 @@ class TimelineBuilder {
1880
2106
  }
1881
2107
  this._currentKeyframe = this._keyframes.get(this.duration);
1882
2108
  if (!this._currentKeyframe) {
1883
- this._currentKeyframe = Object.create(this._backFill, {});
2109
+ this._currentKeyframe = new Map();
1884
2110
  this._keyframes.set(this.duration, this._currentKeyframe);
1885
2111
  }
1886
2112
  }
@@ -1894,16 +2120,16 @@ class TimelineBuilder {
1894
2120
  this._loadKeyframe();
1895
2121
  }
1896
2122
  _updateStyle(prop, value) {
1897
- this._localTimelineStyles[prop] = value;
1898
- this._globalTimelineStyles[prop] = value;
1899
- this._styleSummary[prop] = { time: this.currentTime, value };
2123
+ this._localTimelineStyles.set(prop, value);
2124
+ this._globalTimelineStyles.set(prop, value);
2125
+ this._styleSummary.set(prop, { time: this.currentTime, value });
1900
2126
  }
1901
2127
  allowOnlyTimelineStyles() {
1902
2128
  return this._currentEmptyStepKeyframe !== this._currentKeyframe;
1903
2129
  }
1904
2130
  applyEmptyStep(easing) {
1905
2131
  if (easing) {
1906
- this._previousKeyframe['easing'] = easing;
2132
+ this._previousKeyframe.set('easing', easing);
1907
2133
  }
1908
2134
  // special case for animate(duration):
1909
2135
  // all missing styles are filled with a `*` value then
@@ -1911,51 +2137,45 @@ class TimelineBuilder {
1911
2137
  // keyframe then they will override the overridden styles
1912
2138
  // We use `_globalTimelineStyles` here because there may be
1913
2139
  // styles in previous keyframes that are not present in this timeline
1914
- Object.keys(this._globalTimelineStyles).forEach(prop => {
1915
- this._backFill[prop] = this._globalTimelineStyles[prop] || AUTO_STYLE;
1916
- this._currentKeyframe[prop] = AUTO_STYLE;
1917
- });
2140
+ for (let [prop, value] of this._globalTimelineStyles) {
2141
+ this._backFill.set(prop, value || AUTO_STYLE);
2142
+ this._currentKeyframe.set(prop, AUTO_STYLE);
2143
+ }
1918
2144
  this._currentEmptyStepKeyframe = this._currentKeyframe;
1919
2145
  }
1920
2146
  setStyles(input, easing, errors, options) {
1921
2147
  if (easing) {
1922
- this._previousKeyframe['easing'] = easing;
2148
+ this._previousKeyframe.set('easing', easing);
1923
2149
  }
1924
2150
  const params = (options && options.params) || {};
1925
2151
  const styles = flattenStyles(input, this._globalTimelineStyles);
1926
- Object.keys(styles).forEach(prop => {
1927
- const val = interpolateParams(styles[prop], params, errors);
1928
- this._pendingStyles[prop] = val;
1929
- if (!this._localTimelineStyles.hasOwnProperty(prop)) {
1930
- this._backFill[prop] = this._globalTimelineStyles.hasOwnProperty(prop) ?
1931
- this._globalTimelineStyles[prop] :
1932
- AUTO_STYLE;
2152
+ for (let [prop, value] of styles) {
2153
+ const val = interpolateParams(value, params, errors);
2154
+ this._pendingStyles.set(prop, val);
2155
+ if (!this._localTimelineStyles.has(prop)) {
2156
+ this._backFill.set(prop, this._globalTimelineStyles.get(prop) || AUTO_STYLE);
1933
2157
  }
1934
2158
  this._updateStyle(prop, val);
1935
- });
2159
+ }
1936
2160
  }
1937
2161
  applyStylesToKeyframe() {
1938
- const styles = this._pendingStyles;
1939
- const props = Object.keys(styles);
1940
- if (props.length == 0)
2162
+ if (this._pendingStyles.size == 0)
1941
2163
  return;
1942
- this._pendingStyles = {};
1943
- props.forEach(prop => {
1944
- const val = styles[prop];
1945
- this._currentKeyframe[prop] = val;
2164
+ this._pendingStyles.forEach((val, prop) => {
2165
+ this._currentKeyframe.set(prop, val);
1946
2166
  });
1947
- Object.keys(this._localTimelineStyles).forEach(prop => {
1948
- if (!this._currentKeyframe.hasOwnProperty(prop)) {
1949
- this._currentKeyframe[prop] = this._localTimelineStyles[prop];
2167
+ this._pendingStyles.clear();
2168
+ this._localTimelineStyles.forEach((val, prop) => {
2169
+ if (!this._currentKeyframe.has(prop)) {
2170
+ this._currentKeyframe.set(prop, val);
1950
2171
  }
1951
2172
  });
1952
2173
  }
1953
2174
  snapshotCurrentStyles() {
1954
- Object.keys(this._localTimelineStyles).forEach(prop => {
1955
- const val = this._localTimelineStyles[prop];
1956
- this._pendingStyles[prop] = val;
2175
+ for (let [prop, val] of this._localTimelineStyles) {
2176
+ this._pendingStyles.set(prop, val);
1957
2177
  this._updateStyle(prop, val);
1958
- });
2178
+ }
1959
2179
  }
1960
2180
  getFinalKeyframe() {
1961
2181
  return this._keyframes.get(this.duration);
@@ -1968,9 +2188,8 @@ class TimelineBuilder {
1968
2188
  return properties;
1969
2189
  }
1970
2190
  mergeTimelineCollectedStyles(timeline) {
1971
- Object.keys(timeline._styleSummary).forEach(prop => {
1972
- const details0 = this._styleSummary[prop];
1973
- const details1 = timeline._styleSummary[prop];
2191
+ timeline._styleSummary.forEach((details1, prop) => {
2192
+ const details0 = this._styleSummary.get(prop);
1974
2193
  if (!details0 || details1.time > details0.time) {
1975
2194
  this._updateStyle(prop, details1.value);
1976
2195
  }
@@ -1983,18 +2202,17 @@ class TimelineBuilder {
1983
2202
  const isEmpty = this._keyframes.size === 1 && this.duration === 0;
1984
2203
  let finalKeyframes = [];
1985
2204
  this._keyframes.forEach((keyframe, time) => {
1986
- const finalKeyframe = copyStyles(keyframe, true);
1987
- Object.keys(finalKeyframe).forEach(prop => {
1988
- const value = finalKeyframe[prop];
1989
- if (value == ɵPRE_STYLE) {
2205
+ const finalKeyframe = copyStyles(keyframe, new Map(), this._backFill);
2206
+ finalKeyframe.forEach((value, prop) => {
2207
+ if (value === ɵPRE_STYLE) {
1990
2208
  preStyleProps.add(prop);
1991
2209
  }
1992
- else if (value == AUTO_STYLE) {
2210
+ else if (value === AUTO_STYLE) {
1993
2211
  postStyleProps.add(prop);
1994
2212
  }
1995
2213
  });
1996
2214
  if (!isEmpty) {
1997
- finalKeyframe['offset'] = time / this.duration;
2215
+ finalKeyframe.set('offset', time / this.duration);
1998
2216
  }
1999
2217
  finalKeyframes.push(finalKeyframe);
2000
2218
  });
@@ -2003,9 +2221,9 @@ class TimelineBuilder {
2003
2221
  // special case for a 0-second animation (which is designed just to place styles onscreen)
2004
2222
  if (isEmpty) {
2005
2223
  const kf0 = finalKeyframes[0];
2006
- const kf1 = copyObj(kf0);
2007
- kf0['offset'] = 0;
2008
- kf1['offset'] = 1;
2224
+ const kf1 = new Map(kf0);
2225
+ kf0.set('offset', 0);
2226
+ kf1.set('offset', 1);
2009
2227
  finalKeyframes = [kf0, kf1];
2010
2228
  }
2011
2229
  return createTimelineInstruction(this.element, finalKeyframes, preProps, postProps, this.duration, this.startTime, this.easing, false);
@@ -2031,11 +2249,11 @@ class SubTimelineBuilder extends TimelineBuilder {
2031
2249
  const totalTime = duration + delay;
2032
2250
  const startingGap = delay / totalTime;
2033
2251
  // the original starting keyframe now starts once the delay is done
2034
- const newFirstKeyframe = copyStyles(keyframes[0], false);
2035
- newFirstKeyframe['offset'] = 0;
2252
+ const newFirstKeyframe = copyStyles(keyframes[0]);
2253
+ newFirstKeyframe.set('offset', 0);
2036
2254
  newKeyframes.push(newFirstKeyframe);
2037
- const oldFirstKeyframe = copyStyles(keyframes[0], false);
2038
- oldFirstKeyframe['offset'] = roundOffset(startingGap);
2255
+ const oldFirstKeyframe = copyStyles(keyframes[0]);
2256
+ oldFirstKeyframe.set('offset', roundOffset(startingGap));
2039
2257
  newKeyframes.push(oldFirstKeyframe);
2040
2258
  /*
2041
2259
  When the keyframe is stretched then it means that the delay before the animation
@@ -2054,10 +2272,10 @@ class SubTimelineBuilder extends TimelineBuilder {
2054
2272
  // offsets between 1 ... n -1 are all warped by the keyframe stretch
2055
2273
  const limit = keyframes.length - 1;
2056
2274
  for (let i = 1; i <= limit; i++) {
2057
- let kf = copyStyles(keyframes[i], false);
2058
- const oldOffset = kf['offset'];
2275
+ let kf = copyStyles(keyframes[i]);
2276
+ const oldOffset = kf.get('offset');
2059
2277
  const timeAtKeyframe = delay + oldOffset * duration;
2060
- kf['offset'] = roundOffset(timeAtKeyframe / totalTime);
2278
+ kf.set('offset', roundOffset(timeAtKeyframe / totalTime));
2061
2279
  newKeyframes.push(kf);
2062
2280
  }
2063
2281
  // the new starting keyframe should be added at the start
@@ -2074,17 +2292,17 @@ function roundOffset(offset, decimalPoints = 3) {
2074
2292
  return Math.round(offset * mult) / mult;
2075
2293
  }
2076
2294
  function flattenStyles(input, allStyles) {
2077
- const styles = {};
2295
+ const styles = new Map();
2078
2296
  let allProperties;
2079
2297
  input.forEach(token => {
2080
2298
  if (token === '*') {
2081
- allProperties = allProperties || Object.keys(allStyles);
2082
- allProperties.forEach(prop => {
2083
- styles[prop] = AUTO_STYLE;
2084
- });
2299
+ allProperties = allProperties || allStyles.keys();
2300
+ for (let prop of allProperties) {
2301
+ styles.set(prop, AUTO_STYLE);
2302
+ }
2085
2303
  }
2086
2304
  else {
2087
- copyStyles(token, false, styles);
2305
+ copyStyles(token, styles);
2088
2306
  }
2089
2307
  });
2090
2308
  return styles;
@@ -2150,6 +2368,37 @@ class NoopAnimationStyleNormalizer {
2150
2368
  * Use of this source code is governed by an MIT-style license that can be
2151
2369
  * found in the LICENSE file at https://angular.io/license
2152
2370
  */
2371
+ const DIMENSIONAL_PROP_SET = new Set([
2372
+ 'width',
2373
+ 'height',
2374
+ 'minWidth',
2375
+ 'minHeight',
2376
+ 'maxWidth',
2377
+ 'maxHeight',
2378
+ 'left',
2379
+ 'top',
2380
+ 'bottom',
2381
+ 'right',
2382
+ 'fontSize',
2383
+ 'outlineWidth',
2384
+ 'outlineOffset',
2385
+ 'paddingTop',
2386
+ 'paddingLeft',
2387
+ 'paddingBottom',
2388
+ 'paddingRight',
2389
+ 'marginTop',
2390
+ 'marginLeft',
2391
+ 'marginBottom',
2392
+ 'marginRight',
2393
+ 'borderRadius',
2394
+ 'borderWidth',
2395
+ 'borderTopWidth',
2396
+ 'borderLeftWidth',
2397
+ 'borderRightWidth',
2398
+ 'borderBottomWidth',
2399
+ 'textIndent',
2400
+ 'perspective'
2401
+ ]);
2153
2402
  class WebAnimationsStyleNormalizer extends AnimationStyleNormalizer {
2154
2403
  normalizePropertyName(propertyName, errors) {
2155
2404
  return dashCaseToCamelCase(propertyName);
@@ -2157,7 +2406,7 @@ class WebAnimationsStyleNormalizer extends AnimationStyleNormalizer {
2157
2406
  normalizeStyleValue(userProvidedProperty, normalizedProperty, value, errors) {
2158
2407
  let unit = '';
2159
2408
  const strVal = value.toString().trim();
2160
- if (DIMENSIONAL_PROP_MAP[normalizedProperty] && value !== 0 && value !== '0') {
2409
+ if (DIMENSIONAL_PROP_SET.has(normalizedProperty) && value !== 0 && value !== '0') {
2161
2410
  if (typeof value === 'number') {
2162
2411
  unit = 'px';
2163
2412
  }
@@ -2171,14 +2420,14 @@ class WebAnimationsStyleNormalizer extends AnimationStyleNormalizer {
2171
2420
  return strVal + unit;
2172
2421
  }
2173
2422
  }
2174
- const DIMENSIONAL_PROP_MAP = (() => makeBooleanMap('width,height,minWidth,minHeight,maxWidth,maxHeight,left,top,bottom,right,fontSize,outlineWidth,outlineOffset,paddingTop,paddingLeft,paddingBottom,paddingRight,marginTop,marginLeft,marginBottom,marginRight,borderRadius,borderWidth,borderTopWidth,borderLeftWidth,borderRightWidth,borderBottomWidth,textIndent,perspective'
2175
- .split(',')))();
2176
- function makeBooleanMap(keys) {
2177
- const map = {};
2178
- keys.forEach(key => map[key] = true);
2179
- return map;
2180
- }
2181
2423
 
2424
+ /**
2425
+ * @license
2426
+ * Copyright Google LLC All Rights Reserved.
2427
+ *
2428
+ * Use of this source code is governed by an MIT-style license that can be
2429
+ * found in the LICENSE file at https://angular.io/license
2430
+ */
2182
2431
  function createTransitionInstruction(element, triggerName, fromState, toState, isRemovalTransition, fromStyles, toStyles, timelines, queriedElements, preStyleProps, postStyleProps, totalTime, errors) {
2183
2432
  return {
2184
2433
  type: 0 /* TransitionAnimation */,
@@ -2209,10 +2458,11 @@ class AnimationTransitionFactory {
2209
2458
  return oneOrMoreTransitionsMatch(this.ast.matchers, currentState, nextState, element, params);
2210
2459
  }
2211
2460
  buildStyles(stateName, params, errors) {
2212
- const backupStateStyler = this._stateStyles['*'];
2213
- const stateStyler = this._stateStyles[stateName];
2214
- const backupStyles = backupStateStyler ? backupStateStyler.buildStyles(params, errors) : {};
2215
- return stateStyler ? stateStyler.buildStyles(params, errors) : backupStyles;
2461
+ let styler = this._stateStyles.get('*');
2462
+ if (stateName !== undefined) {
2463
+ styler = this._stateStyles.get(stateName?.toString()) || styler;
2464
+ }
2465
+ return styler ? styler.buildStyles(params, errors) : new Map();
2216
2466
  }
2217
2467
  build(driver, element, currentState, nextState, enterClassName, leaveClassName, currentOptions, nextOptions, subInstructions, skipAstBuild) {
2218
2468
  const errors = [];
@@ -2225,7 +2475,10 @@ class AnimationTransitionFactory {
2225
2475
  const preStyleMap = new Map();
2226
2476
  const postStyleMap = new Map();
2227
2477
  const isRemoval = nextState === 'void';
2228
- const animationOptions = { params: { ...transitionAnimationParams, ...nextAnimationParams } };
2478
+ const animationOptions = {
2479
+ params: applyParamDefaults(nextAnimationParams, transitionAnimationParams),
2480
+ delay: this.ast.options?.delay,
2481
+ };
2229
2482
  const timelines = skipAstBuild ?
2230
2483
  [] :
2231
2484
  buildAnimationTimelines(driver, element, this.ast.animation, enterClassName, leaveClassName, currentStateStyles, nextStateStyles, animationOptions, subInstructions, errors);
@@ -2238,10 +2491,10 @@ class AnimationTransitionFactory {
2238
2491
  }
2239
2492
  timelines.forEach(tl => {
2240
2493
  const elm = tl.element;
2241
- const preProps = getOrSetAsInMap(preStyleMap, elm, {});
2242
- tl.preStyleProps.forEach(prop => preProps[prop] = true);
2243
- const postProps = getOrSetAsInMap(postStyleMap, elm, {});
2244
- tl.postStyleProps.forEach(prop => postProps[prop] = true);
2494
+ const preProps = getOrSetDefaultValue(preStyleMap, elm, new Set());
2495
+ tl.preStyleProps.forEach(prop => preProps.add(prop));
2496
+ const postProps = getOrSetDefaultValue(postStyleMap, elm, new Set());
2497
+ tl.postStyleProps.forEach(prop => postProps.add(prop));
2245
2498
  if (elm !== element) {
2246
2499
  queriedElements.add(elm);
2247
2500
  }
@@ -2253,6 +2506,15 @@ class AnimationTransitionFactory {
2253
2506
  function oneOrMoreTransitionsMatch(matchFns, currentState, nextState, element, params) {
2254
2507
  return matchFns.some(fn => fn(currentState, nextState, element, params));
2255
2508
  }
2509
+ function applyParamDefaults(userParams, defaults) {
2510
+ const result = copyObj(defaults);
2511
+ for (const key in userParams) {
2512
+ if (userParams.hasOwnProperty(key) && userParams[key] != null) {
2513
+ result[key] = userParams[key];
2514
+ }
2515
+ }
2516
+ return result;
2517
+ }
2256
2518
  class AnimationStateStyles {
2257
2519
  constructor(styles, defaultParams, normalizer) {
2258
2520
  this.styles = styles;
@@ -2260,25 +2522,23 @@ class AnimationStateStyles {
2260
2522
  this.normalizer = normalizer;
2261
2523
  }
2262
2524
  buildStyles(params, errors) {
2263
- const finalStyles = {};
2525
+ const finalStyles = new Map();
2264
2526
  const combinedParams = copyObj(this.defaultParams);
2265
2527
  Object.keys(params).forEach(key => {
2266
2528
  const value = params[key];
2267
- if (value != null) {
2529
+ if (value !== null) {
2268
2530
  combinedParams[key] = value;
2269
2531
  }
2270
2532
  });
2271
2533
  this.styles.styles.forEach(value => {
2272
2534
  if (typeof value !== 'string') {
2273
- const styleObj = value;
2274
- Object.keys(styleObj).forEach(prop => {
2275
- let val = styleObj[prop];
2276
- if (val.length > 1) {
2535
+ value.forEach((val, prop) => {
2536
+ if (val) {
2277
2537
  val = interpolateParams(val, combinedParams, errors);
2278
2538
  }
2279
2539
  const normalizedProp = this.normalizer.normalizePropertyName(prop, errors);
2280
2540
  val = this.normalizer.normalizeStyleValue(prop, normalizedProp, val, errors);
2281
- finalStyles[normalizedProp] = val;
2541
+ finalStyles.set(normalizedProp, val);
2282
2542
  });
2283
2543
  }
2284
2544
  });
@@ -2295,10 +2555,10 @@ class AnimationTrigger {
2295
2555
  this.ast = ast;
2296
2556
  this._normalizer = _normalizer;
2297
2557
  this.transitionFactories = [];
2298
- this.states = {};
2558
+ this.states = new Map();
2299
2559
  ast.states.forEach(ast => {
2300
2560
  const defaultParams = (ast.options && ast.options.params) || {};
2301
- this.states[ast.name] = new AnimationStateStyles(ast.style, defaultParams, _normalizer);
2561
+ this.states.set(ast.name, new AnimationStateStyles(ast.style, defaultParams, _normalizer));
2302
2562
  });
2303
2563
  balanceProperties(this.states, 'true', '1');
2304
2564
  balanceProperties(this.states, 'false', '0');
@@ -2331,14 +2591,14 @@ function createFallbackTransition(triggerName, states, normalizer) {
2331
2591
  };
2332
2592
  return new AnimationTransitionFactory(triggerName, transition, states);
2333
2593
  }
2334
- function balanceProperties(obj, key1, key2) {
2335
- if (obj.hasOwnProperty(key1)) {
2336
- if (!obj.hasOwnProperty(key2)) {
2337
- obj[key2] = obj[key1];
2594
+ function balanceProperties(stateMap, key1, key2) {
2595
+ if (stateMap.has(key1)) {
2596
+ if (!stateMap.has(key2)) {
2597
+ stateMap.set(key2, stateMap.get(key1));
2338
2598
  }
2339
2599
  }
2340
- else if (obj.hasOwnProperty(key2)) {
2341
- obj[key1] = obj[key2];
2600
+ else if (stateMap.has(key2)) {
2601
+ stateMap.set(key1, stateMap.get(key2));
2342
2602
  }
2343
2603
  }
2344
2604
 
@@ -2355,8 +2615,8 @@ class TimelineAnimationEngine {
2355
2615
  this.bodyNode = bodyNode;
2356
2616
  this._driver = _driver;
2357
2617
  this._normalizer = _normalizer;
2358
- this._animations = {};
2359
- this._playersById = {};
2618
+ this._animations = new Map();
2619
+ this._playersById = new Map();
2360
2620
  this.players = [];
2361
2621
  }
2362
2622
  register(id, metadata) {
@@ -2370,24 +2630,24 @@ class TimelineAnimationEngine {
2370
2630
  if (warnings.length) {
2371
2631
  warnRegister(warnings);
2372
2632
  }
2373
- this._animations[id] = ast;
2633
+ this._animations.set(id, ast);
2374
2634
  }
2375
2635
  }
2376
2636
  _buildPlayer(i, preStyles, postStyles) {
2377
2637
  const element = i.element;
2378
- const keyframes = normalizeKeyframes(this._driver, this._normalizer, element, i.keyframes, preStyles, postStyles);
2638
+ const keyframes = normalizeKeyframes$1(this._driver, this._normalizer, element, i.keyframes, preStyles, postStyles);
2379
2639
  return this._driver.animate(element, keyframes, i.duration, i.delay, i.easing, [], true);
2380
2640
  }
2381
2641
  create(id, element, options = {}) {
2382
2642
  const errors = [];
2383
- const ast = this._animations[id];
2643
+ const ast = this._animations.get(id);
2384
2644
  let instructions;
2385
2645
  const autoStylesMap = new Map();
2386
2646
  if (ast) {
2387
- instructions = buildAnimationTimelines(this._driver, element, ast, ENTER_CLASSNAME, LEAVE_CLASSNAME, {}, {}, options, EMPTY_INSTRUCTION_MAP, errors);
2647
+ instructions = buildAnimationTimelines(this._driver, element, ast, ENTER_CLASSNAME, LEAVE_CLASSNAME, new Map(), new Map(), options, EMPTY_INSTRUCTION_MAP, errors);
2388
2648
  instructions.forEach(inst => {
2389
- const styles = getOrSetAsInMap(autoStylesMap, inst.element, {});
2390
- inst.postStyleProps.forEach(prop => styles[prop] = null);
2649
+ const styles = getOrSetDefaultValue(autoStylesMap, inst.element, new Map());
2650
+ inst.postStyleProps.forEach(prop => styles.set(prop, null));
2391
2651
  });
2392
2652
  }
2393
2653
  else {
@@ -2398,16 +2658,16 @@ class TimelineAnimationEngine {
2398
2658
  throw createAnimationFailed(errors);
2399
2659
  }
2400
2660
  autoStylesMap.forEach((styles, element) => {
2401
- Object.keys(styles).forEach(prop => {
2402
- styles[prop] = this._driver.computeStyle(element, prop, AUTO_STYLE);
2661
+ styles.forEach((_, prop) => {
2662
+ styles.set(prop, this._driver.computeStyle(element, prop, AUTO_STYLE));
2403
2663
  });
2404
2664
  });
2405
2665
  const players = instructions.map(i => {
2406
2666
  const styles = autoStylesMap.get(i.element);
2407
- return this._buildPlayer(i, {}, styles);
2667
+ return this._buildPlayer(i, new Map(), styles);
2408
2668
  });
2409
2669
  const player = optimizeGroupPlayer(players);
2410
- this._playersById[id] = player;
2670
+ this._playersById.set(id, player);
2411
2671
  player.onDestroy(() => this.destroy(id));
2412
2672
  this.players.push(player);
2413
2673
  return player;
@@ -2415,14 +2675,14 @@ class TimelineAnimationEngine {
2415
2675
  destroy(id) {
2416
2676
  const player = this._getPlayer(id);
2417
2677
  player.destroy();
2418
- delete this._playersById[id];
2678
+ this._playersById.delete(id);
2419
2679
  const index = this.players.indexOf(player);
2420
2680
  if (index >= 0) {
2421
2681
  this.players.splice(index, 1);
2422
2682
  }
2423
2683
  }
2424
2684
  _getPlayer(id) {
2425
- const player = this._playersById[id];
2685
+ const player = this._playersById.get(id);
2426
2686
  if (!player) {
2427
2687
  throw missingPlayer(id);
2428
2688
  }
@@ -2544,14 +2804,14 @@ class AnimationTransitionNamespace {
2544
2804
  this.hostElement = hostElement;
2545
2805
  this._engine = _engine;
2546
2806
  this.players = [];
2547
- this._triggers = {};
2807
+ this._triggers = new Map();
2548
2808
  this._queue = [];
2549
2809
  this._elementListeners = new Map();
2550
2810
  this._hostClassName = 'ng-tns-' + id;
2551
2811
  addClass(hostElement, this._hostClassName);
2552
2812
  }
2553
2813
  listen(element, name, phase, callback) {
2554
- if (!this._triggers.hasOwnProperty(name)) {
2814
+ if (!this._triggers.has(name)) {
2555
2815
  throw missingTrigger(phase, name);
2556
2816
  }
2557
2817
  if (phase == null || phase.length == 0) {
@@ -2560,14 +2820,14 @@ class AnimationTransitionNamespace {
2560
2820
  if (!isTriggerEventValid(phase)) {
2561
2821
  throw unsupportedTriggerEvent(phase, name);
2562
2822
  }
2563
- const listeners = getOrSetAsInMap(this._elementListeners, element, []);
2823
+ const listeners = getOrSetDefaultValue(this._elementListeners, element, []);
2564
2824
  const data = { name, phase, callback };
2565
2825
  listeners.push(data);
2566
- const triggersWithStates = getOrSetAsInMap(this._engine.statesByElement, element, {});
2567
- if (!triggersWithStates.hasOwnProperty(name)) {
2826
+ const triggersWithStates = getOrSetDefaultValue(this._engine.statesByElement, element, new Map());
2827
+ if (!triggersWithStates.has(name)) {
2568
2828
  addClass(element, NG_TRIGGER_CLASSNAME);
2569
2829
  addClass(element, NG_TRIGGER_CLASSNAME + '-' + name);
2570
- triggersWithStates[name] = DEFAULT_STATE_VALUE;
2830
+ triggersWithStates.set(name, DEFAULT_STATE_VALUE);
2571
2831
  }
2572
2832
  return () => {
2573
2833
  // the event listener is removed AFTER the flush has occurred such
@@ -2578,24 +2838,24 @@ class AnimationTransitionNamespace {
2578
2838
  if (index >= 0) {
2579
2839
  listeners.splice(index, 1);
2580
2840
  }
2581
- if (!this._triggers[name]) {
2582
- delete triggersWithStates[name];
2841
+ if (!this._triggers.has(name)) {
2842
+ triggersWithStates.delete(name);
2583
2843
  }
2584
2844
  });
2585
2845
  };
2586
2846
  }
2587
2847
  register(name, ast) {
2588
- if (this._triggers[name]) {
2848
+ if (this._triggers.has(name)) {
2589
2849
  // throw
2590
2850
  return false;
2591
2851
  }
2592
2852
  else {
2593
- this._triggers[name] = ast;
2853
+ this._triggers.set(name, ast);
2594
2854
  return true;
2595
2855
  }
2596
2856
  }
2597
2857
  _getTrigger(name) {
2598
- const trigger = this._triggers[name];
2858
+ const trigger = this._triggers.get(name);
2599
2859
  if (!trigger) {
2600
2860
  throw unregisteredTrigger(name);
2601
2861
  }
@@ -2608,15 +2868,15 @@ class AnimationTransitionNamespace {
2608
2868
  if (!triggersWithStates) {
2609
2869
  addClass(element, NG_TRIGGER_CLASSNAME);
2610
2870
  addClass(element, NG_TRIGGER_CLASSNAME + '-' + triggerName);
2611
- this._engine.statesByElement.set(element, triggersWithStates = {});
2871
+ this._engine.statesByElement.set(element, triggersWithStates = new Map());
2612
2872
  }
2613
- let fromState = triggersWithStates[triggerName];
2873
+ let fromState = triggersWithStates.get(triggerName);
2614
2874
  const toState = new StateValue(value, this.id);
2615
2875
  const isObj = value && value.hasOwnProperty('value');
2616
2876
  if (!isObj && fromState) {
2617
2877
  toState.absorbOptions(fromState.options);
2618
2878
  }
2619
- triggersWithStates[triggerName] = toState;
2879
+ triggersWithStates.set(triggerName, toState);
2620
2880
  if (!fromState) {
2621
2881
  fromState = DEFAULT_STATE_VALUE;
2622
2882
  }
@@ -2646,7 +2906,7 @@ class AnimationTransitionNamespace {
2646
2906
  }
2647
2907
  return;
2648
2908
  }
2649
- const playersOnElement = getOrSetAsInMap(this._engine.playersByElement, element, []);
2909
+ const playersOnElement = getOrSetDefaultValue(this._engine.playersByElement, element, []);
2650
2910
  playersOnElement.forEach(player => {
2651
2911
  // only remove the player if it is queued on the EXACT same trigger/namespace
2652
2912
  // we only also deal with queued players here because if the animation has
@@ -2690,10 +2950,8 @@ class AnimationTransitionNamespace {
2690
2950
  return player;
2691
2951
  }
2692
2952
  deregister(name) {
2693
- delete this._triggers[name];
2694
- this._engine.statesByElement.forEach((stateMap, element) => {
2695
- delete stateMap[name];
2696
- });
2953
+ this._triggers.delete(name);
2954
+ this._engine.statesByElement.forEach(stateMap => stateMap.delete(name));
2697
2955
  this._elementListeners.forEach((listeners, element) => {
2698
2956
  this._elementListeners.set(element, listeners.filter(entry => {
2699
2957
  return entry.name != name;
@@ -2736,11 +2994,11 @@ class AnimationTransitionNamespace {
2736
2994
  const previousTriggersValues = new Map();
2737
2995
  if (triggerStates) {
2738
2996
  const players = [];
2739
- Object.keys(triggerStates).forEach(triggerName => {
2740
- previousTriggersValues.set(triggerName, triggerStates[triggerName].value);
2997
+ triggerStates.forEach((state, triggerName) => {
2998
+ previousTriggersValues.set(triggerName, state.value);
2741
2999
  // this check is here in the event that an element is removed
2742
3000
  // twice (both on the host level and the component level)
2743
- if (this._triggers[triggerName]) {
3001
+ if (this._triggers.has(triggerName)) {
2744
3002
  const player = this.trigger(element, triggerName, VOID_VALUE, defaultToFallback);
2745
3003
  if (player) {
2746
3004
  players.push(player);
@@ -2769,9 +3027,9 @@ class AnimationTransitionNamespace {
2769
3027
  if (visitedTriggers.has(triggerName))
2770
3028
  return;
2771
3029
  visitedTriggers.add(triggerName);
2772
- const trigger = this._triggers[triggerName];
3030
+ const trigger = this._triggers.get(triggerName);
2773
3031
  const transition = trigger.fallbackTransition;
2774
- const fromState = elementStates[triggerName] || DEFAULT_STATE_VALUE;
3032
+ const fromState = elementStates.get(triggerName) || DEFAULT_STATE_VALUE;
2775
3033
  const toState = new StateValue(VOID_VALUE);
2776
3034
  const player = new TransitionAnimationPlayer(this.id, triggerName, element);
2777
3035
  this._engine.totalQueuedPlayers++;
@@ -2958,35 +3216,20 @@ class TransitionAnimationEngine {
2958
3216
  const limit = namespaceList.length - 1;
2959
3217
  if (limit >= 0) {
2960
3218
  let found = false;
2961
- if (this.driver.getParentElement !== undefined) {
2962
- // Fast path for when the driver implements `getParentElement`, which allows us to find the
2963
- // closest ancestor with an existing namespace that we can then insert `ns` after, without
2964
- // having to inspect all existing namespaces.
2965
- let ancestor = this.driver.getParentElement(hostElement);
2966
- while (ancestor) {
2967
- const ancestorNs = namespacesByHostElement.get(ancestor);
2968
- if (ancestorNs) {
2969
- // An animation namespace has been registered for this ancestor, so we insert `ns`
2970
- // right after it to establish top-down ordering of animation namespaces.
2971
- const index = namespaceList.indexOf(ancestorNs);
2972
- namespaceList.splice(index + 1, 0, ns);
2973
- found = true;
2974
- break;
2975
- }
2976
- ancestor = this.driver.getParentElement(ancestor);
2977
- }
2978
- }
2979
- else {
2980
- // Slow path for backwards compatibility if the driver does not implement
2981
- // `getParentElement`, to be removed once `getParentElement` is a required method.
2982
- for (let i = limit; i >= 0; i--) {
2983
- const nextNamespace = namespaceList[i];
2984
- if (this.driver.containsElement(nextNamespace.hostElement, hostElement)) {
2985
- namespaceList.splice(i + 1, 0, ns);
2986
- found = true;
2987
- break;
2988
- }
3219
+ // Find the closest ancestor with an existing namespace so we can then insert `ns` after it,
3220
+ // establishing a top-down ordering of namespaces in `this._namespaceList`.
3221
+ let ancestor = this.driver.getParentElement(hostElement);
3222
+ while (ancestor) {
3223
+ const ancestorNs = namespacesByHostElement.get(ancestor);
3224
+ if (ancestorNs) {
3225
+ // An animation namespace has been registered for this ancestor, so we insert `ns`
3226
+ // right after it to establish top-down ordering of animation namespaces.
3227
+ const index = namespaceList.indexOf(ancestorNs);
3228
+ namespaceList.splice(index + 1, 0, ns);
3229
+ found = true;
3230
+ break;
2989
3231
  }
3232
+ ancestor = this.driver.getParentElement(ancestor);
2990
3233
  }
2991
3234
  if (!found) {
2992
3235
  // No namespace exists that is an ancestor of `ns`, so `ns` is inserted at the front to
@@ -3040,11 +3283,9 @@ class TransitionAnimationEngine {
3040
3283
  const namespaces = new Set();
3041
3284
  const elementStates = this.statesByElement.get(element);
3042
3285
  if (elementStates) {
3043
- const keys = Object.keys(elementStates);
3044
- for (let i = 0; i < keys.length; i++) {
3045
- const nsId = elementStates[keys[i]].namespaceId;
3046
- if (nsId) {
3047
- const ns = this._fetchNamespace(nsId);
3286
+ for (let stateValue of elementStates.values()) {
3287
+ if (stateValue.namespaceId) {
3288
+ const ns = this._fetchNamespace(stateValue.namespaceId);
3048
3289
  if (ns) {
3049
3290
  namespaces.add(ns);
3050
3291
  }
@@ -3351,8 +3592,10 @@ class TransitionAnimationEngine {
3351
3592
  // we need to restore the previous trigger value since the element has
3352
3593
  // only been moved and hasn't actually left the DOM
3353
3594
  const triggersWithStates = this.statesByElement.get(entry.element);
3354
- if (triggersWithStates && triggersWithStates[entry.triggerName]) {
3355
- triggersWithStates[entry.triggerName].value = previousValue;
3595
+ if (triggersWithStates && triggersWithStates.has(entry.triggerName)) {
3596
+ const state = triggersWithStates.get(entry.triggerName);
3597
+ state.value = previousValue;
3598
+ triggersWithStates.set(entry.triggerName, state);
3356
3599
  }
3357
3600
  }
3358
3601
  player.destroy();
@@ -3402,24 +3645,22 @@ class TransitionAnimationEngine {
3402
3645
  subTimelines.append(element, instruction.timelines);
3403
3646
  const tuple = { instruction, player, element };
3404
3647
  queuedInstructions.push(tuple);
3405
- instruction.queriedElements.forEach(element => getOrSetAsInMap(queriedElements, element, []).push(player));
3648
+ instruction.queriedElements.forEach(element => getOrSetDefaultValue(queriedElements, element, []).push(player));
3406
3649
  instruction.preStyleProps.forEach((stringMap, element) => {
3407
- const props = Object.keys(stringMap);
3408
- if (props.length) {
3650
+ if (stringMap.size) {
3409
3651
  let setVal = allPreStyleElements.get(element);
3410
3652
  if (!setVal) {
3411
3653
  allPreStyleElements.set(element, setVal = new Set());
3412
3654
  }
3413
- props.forEach(prop => setVal.add(prop));
3655
+ stringMap.forEach((_, prop) => setVal.add(prop));
3414
3656
  }
3415
3657
  });
3416
3658
  instruction.postStyleProps.forEach((stringMap, element) => {
3417
- const props = Object.keys(stringMap);
3418
3659
  let setVal = allPostStyleElements.get(element);
3419
3660
  if (!setVal) {
3420
3661
  allPostStyleElements.set(element, setVal = new Set());
3421
3662
  }
3422
- props.forEach(prop => setVal.add(prop));
3663
+ stringMap.forEach((_, prop) => setVal.add(prop));
3423
3664
  });
3424
3665
  });
3425
3666
  }
@@ -3448,7 +3689,7 @@ class TransitionAnimationEngine {
3448
3689
  const element = player.element;
3449
3690
  const previousPlayers = this._getPreviousPlayers(element, false, player.namespaceId, player.triggerName, null);
3450
3691
  previousPlayers.forEach(prevPlayer => {
3451
- getOrSetAsInMap(allPreviousPlayersMap, element, []).push(prevPlayer);
3692
+ getOrSetDefaultValue(allPreviousPlayersMap, element, []).push(prevPlayer);
3452
3693
  prevPlayer.destroy();
3453
3694
  });
3454
3695
  });
@@ -3478,7 +3719,7 @@ class TransitionAnimationEngine {
3478
3719
  replaceNodes.forEach(node => {
3479
3720
  const post = postStylesMap.get(node);
3480
3721
  const pre = preStylesMap.get(node);
3481
- postStylesMap.set(node, { ...post, ...pre });
3722
+ postStylesMap.set(node, new Map([...Array.from(post?.entries() ?? []), ...Array.from(pre?.entries() ?? [])]));
3482
3723
  });
3483
3724
  const rootPlayers = [];
3484
3725
  const subPlayers = [];
@@ -3672,7 +3913,7 @@ class TransitionAnimationEngine {
3672
3913
  for (const timelineInstruction of instruction.timelines) {
3673
3914
  const element = timelineInstruction.element;
3674
3915
  const isQueriedElement = element !== rootElement;
3675
- const players = getOrSetAsInMap(allPreviousPlayersMap, element, []);
3916
+ const players = getOrSetDefaultValue(allPreviousPlayersMap, element, []);
3676
3917
  const previousPlayers = this._getPreviousPlayers(element, isQueriedElement, targetNameSpaceId, targetTriggerName, instruction.toState);
3677
3918
  previousPlayers.forEach(player => {
3678
3919
  const realPlayer = player.getRealPlayer();
@@ -3715,7 +3956,7 @@ class TransitionAnimationEngine {
3715
3956
  });
3716
3957
  const preStyles = preStylesMap.get(element);
3717
3958
  const postStyles = postStylesMap.get(element);
3718
- const keyframes = normalizeKeyframes(this.driver, this._normalizer, element, timelineInstruction.keyframes, preStyles, postStyles);
3959
+ const keyframes = normalizeKeyframes$1(this.driver, this._normalizer, element, timelineInstruction.keyframes, preStyles, postStyles);
3719
3960
  const player = this._buildPlayer(timelineInstruction, keyframes, previousPlayers);
3720
3961
  // this means that this particular player belongs to a sub trigger. It is
3721
3962
  // important that we match this player up with the corresponding (@trigger.listener)
@@ -3730,7 +3971,7 @@ class TransitionAnimationEngine {
3730
3971
  return player;
3731
3972
  });
3732
3973
  allQueriedPlayers.forEach(player => {
3733
- getOrSetAsInMap(this.playersByQueriedElement, player.element, []).push(player);
3974
+ getOrSetDefaultValue(this.playersByQueriedElement, player.element, []).push(player);
3734
3975
  player.onDone(() => deleteOrUnsetInMap(this.playersByQueriedElement, player.element, player));
3735
3976
  });
3736
3977
  allConsumedElements.forEach(element => addClass(element, NG_ANIMATING_CLASSNAME));
@@ -3742,7 +3983,7 @@ class TransitionAnimationEngine {
3742
3983
  // this basically makes all of the callbacks for sub element animations
3743
3984
  // be dependent on the upper players for when they finish
3744
3985
  allSubElements.forEach(element => {
3745
- getOrSetAsInMap(skippedPlayersMap, element, []).push(player);
3986
+ getOrSetDefaultValue(skippedPlayersMap, element, []).push(player);
3746
3987
  });
3747
3988
  return player;
3748
3989
  }
@@ -3762,7 +4003,7 @@ class TransitionAnimationPlayer {
3762
4003
  this.element = element;
3763
4004
  this._player = new NoopAnimationPlayer();
3764
4005
  this._containsRealPlayer = false;
3765
- this._queuedCallbacks = {};
4006
+ this._queuedCallbacks = new Map();
3766
4007
  this.destroyed = false;
3767
4008
  this.markedForDestroy = false;
3768
4009
  this.disabled = false;
@@ -3773,10 +4014,10 @@ class TransitionAnimationPlayer {
3773
4014
  if (this._containsRealPlayer)
3774
4015
  return;
3775
4016
  this._player = player;
3776
- Object.keys(this._queuedCallbacks).forEach(phase => {
3777
- this._queuedCallbacks[phase].forEach(callback => listenOnPlayer(player, phase, undefined, callback));
4017
+ this._queuedCallbacks.forEach((callbacks, phase) => {
4018
+ callbacks.forEach(callback => listenOnPlayer(player, phase, undefined, callback));
3778
4019
  });
3779
- this._queuedCallbacks = {};
4020
+ this._queuedCallbacks.clear();
3780
4021
  this._containsRealPlayer = true;
3781
4022
  this.overrideTotalTime(player.totalTime);
3782
4023
  this.queued = false;
@@ -3796,7 +4037,7 @@ class TransitionAnimationPlayer {
3796
4037
  player.onDestroy(() => this.destroy());
3797
4038
  }
3798
4039
  _queueEvent(name, callback) {
3799
- getOrSetAsInMap(this._queuedCallbacks, name, []).push(callback);
4040
+ getOrSetDefaultValue(this._queuedCallbacks, name, []).push(callback);
3800
4041
  }
3801
4042
  onDone(fn) {
3802
4043
  if (this.queued) {
@@ -3858,29 +4099,14 @@ class TransitionAnimationPlayer {
3858
4099
  }
3859
4100
  }
3860
4101
  function deleteOrUnsetInMap(map, key, value) {
3861
- let currentValues;
3862
- if (map instanceof Map) {
3863
- currentValues = map.get(key);
3864
- if (currentValues) {
3865
- if (currentValues.length) {
3866
- const index = currentValues.indexOf(value);
3867
- currentValues.splice(index, 1);
3868
- }
3869
- if (currentValues.length == 0) {
3870
- map.delete(key);
3871
- }
4102
+ let currentValues = map.get(key);
4103
+ if (currentValues) {
4104
+ if (currentValues.length) {
4105
+ const index = currentValues.indexOf(value);
4106
+ currentValues.splice(index, 1);
3872
4107
  }
3873
- }
3874
- else {
3875
- currentValues = map[key];
3876
- if (currentValues) {
3877
- if (currentValues.length) {
3878
- const index = currentValues.indexOf(value);
3879
- currentValues.splice(index, 1);
3880
- }
3881
- if (currentValues.length == 0) {
3882
- delete map[key];
3883
- }
4108
+ if (currentValues.length == 0) {
4109
+ map.delete(key);
3884
4110
  }
3885
4111
  }
3886
4112
  return currentValues;
@@ -3907,9 +4133,10 @@ function cloakAndComputeStyles(valuesMap, driver, elements, elementPropsMap, def
3907
4133
  elements.forEach(element => cloakVals.push(cloakElement(element)));
3908
4134
  const failedElements = [];
3909
4135
  elementPropsMap.forEach((props, element) => {
3910
- const styles = {};
4136
+ const styles = new Map();
3911
4137
  props.forEach(prop => {
3912
- const value = styles[prop] = driver.computeStyle(element, prop, defaultStyle);
4138
+ const value = driver.computeStyle(element, prop, defaultStyle);
4139
+ styles.set(prop, value);
3913
4140
  // there is no easy way to detect this because a sub element could be removed
3914
4141
  // by a parent animation element being detached.
3915
4142
  if (!value || value.length == 0) {
@@ -4097,13 +4324,6 @@ class AnimationEngine {
4097
4324
  }
4098
4325
  }
4099
4326
 
4100
- /**
4101
- * @license
4102
- * Copyright Google LLC All Rights Reserved.
4103
- *
4104
- * Use of this source code is governed by an MIT-style license that can be
4105
- * found in the LICENSE file at https://angular.io/license
4106
- */
4107
4327
  /**
4108
4328
  * Returns an instance of `SpecialCasedStyles` if and when any special (non animateable) styles are
4109
4329
  * detected.
@@ -4124,7 +4344,7 @@ function packageNonAnimatableStyles(element, styles) {
4124
4344
  endStyles = filterNonAnimatableStyles(styles[styles.length - 1]);
4125
4345
  }
4126
4346
  }
4127
- else if (styles) {
4347
+ else if (styles instanceof Map) {
4128
4348
  startStyles = filterNonAnimatableStyles(styles);
4129
4349
  }
4130
4350
  return (startStyles || endStyles) ? new SpecialCasedStyles(element, startStyles, endStyles) :
@@ -4146,7 +4366,7 @@ class SpecialCasedStyles {
4146
4366
  this._state = 0 /* Pending */;
4147
4367
  let initialStyles = SpecialCasedStyles.initialStylesByElement.get(_element);
4148
4368
  if (!initialStyles) {
4149
- SpecialCasedStyles.initialStylesByElement.set(_element, initialStyles = {});
4369
+ SpecialCasedStyles.initialStylesByElement.set(_element, initialStyles = new Map());
4150
4370
  }
4151
4371
  this._initialStyles = initialStyles;
4152
4372
  }
@@ -4189,14 +4409,12 @@ class SpecialCasedStyles {
4189
4409
  SpecialCasedStyles.initialStylesByElement = ( /* @__PURE__ */new WeakMap());
4190
4410
  function filterNonAnimatableStyles(styles) {
4191
4411
  let result = null;
4192
- const props = Object.keys(styles);
4193
- for (let i = 0; i < props.length; i++) {
4194
- const prop = props[i];
4412
+ styles.forEach((val, prop) => {
4195
4413
  if (isNonAnimatableStyle(prop)) {
4196
- result = result || {};
4197
- result[prop] = styles[prop];
4414
+ result = result || new Map();
4415
+ result.set(prop, val);
4198
4416
  }
4199
- }
4417
+ });
4200
4418
  return result;
4201
4419
  }
4202
4420
  function isNonAnimatableStyle(prop) {
@@ -4218,7 +4436,7 @@ class WebAnimationsPlayer {
4218
4436
  this._destroyed = false;
4219
4437
  this.time = 0;
4220
4438
  this.parentPlayer = null;
4221
- this.currentSnapshot = {};
4439
+ this.currentSnapshot = new Map();
4222
4440
  this._duration = options['duration'];
4223
4441
  this._delay = options['delay'] || 0;
4224
4442
  this.time = this._duration + this._delay;
@@ -4241,7 +4459,7 @@ class WebAnimationsPlayer {
4241
4459
  const keyframes = this.keyframes;
4242
4460
  this.domPlayer =
4243
4461
  this._triggerWebAnimation(this.element, keyframes, this.options);
4244
- this._finalKeyframe = keyframes.length ? keyframes[keyframes.length - 1] : {};
4462
+ this._finalKeyframe = keyframes.length ? keyframes[keyframes.length - 1] : new Map();
4245
4463
  this.domPlayer.addEventListener('finish', () => this._onFinish());
4246
4464
  }
4247
4465
  _preparePlayerBeforeStart() {
@@ -4253,11 +4471,18 @@ class WebAnimationsPlayer {
4253
4471
  this.domPlayer.pause();
4254
4472
  }
4255
4473
  }
4474
+ _convertKeyframesToObject(keyframes) {
4475
+ const kfs = [];
4476
+ keyframes.forEach(frame => {
4477
+ kfs.push(Object.fromEntries(frame));
4478
+ });
4479
+ return kfs;
4480
+ }
4256
4481
  /** @internal */
4257
4482
  _triggerWebAnimation(element, keyframes, options) {
4258
4483
  // jscompiler doesn't seem to know animate is a native property because it's not fully
4259
4484
  // supported yet across common browsers (we polyfill it for Edge/Safari) [CL #143630929]
4260
- return element['animate'](keyframes, options);
4485
+ return element['animate'](this._convertKeyframesToObject(keyframes), options);
4261
4486
  }
4262
4487
  onStart(fn) {
4263
4488
  this._onStartFns.push(fn);
@@ -4335,15 +4560,15 @@ class WebAnimationsPlayer {
4335
4560
  return this._delay + this._duration;
4336
4561
  }
4337
4562
  beforeDestroy() {
4338
- const styles = {};
4563
+ const styles = new Map();
4339
4564
  if (this.hasStarted()) {
4340
4565
  // note: this code is invoked only when the `play` function was called prior to this
4341
4566
  // (thus `hasStarted` returns true), this implies that the code that initializes
4342
4567
  // `_finalKeyframe` has also been executed and the non-null assertion can be safely used here
4343
4568
  const finalKeyframe = this._finalKeyframe;
4344
- Object.keys(finalKeyframe).forEach(prop => {
4345
- if (prop != 'offset') {
4346
- styles[prop] = this._finished ? finalKeyframe[prop] : computeStyle(this.element, prop);
4569
+ finalKeyframe.forEach((val, prop) => {
4570
+ if (prop !== 'offset') {
4571
+ styles.set(prop, this._finished ? val : computeStyle(this.element, prop));
4347
4572
  }
4348
4573
  });
4349
4574
  }
@@ -4351,7 +4576,7 @@ class WebAnimationsPlayer {
4351
4576
  }
4352
4577
  /** @internal */
4353
4578
  triggerCallback(phaseName) {
4354
- const methods = phaseName == 'start' ? this._onStartFns : this._onDoneFns;
4579
+ const methods = phaseName === 'start' ? this._onStartFns : this._onDoneFns;
4355
4580
  methods.forEach(fn => fn());
4356
4581
  methods.length = 0;
4357
4582
  }
@@ -4361,6 +4586,14 @@ class WebAnimationsDriver {
4361
4586
  validateStyleProperty(prop) {
4362
4587
  return validateStyleProperty(prop);
4363
4588
  }
4589
+ validateAnimatableStyleProperty(prop) {
4590
+ // Perform actual validation in dev mode only, in prod mode this check is a noop.
4591
+ if (ngDevMode) {
4592
+ const cssProp = camelCaseToDashCase(prop);
4593
+ return validateWebAnimatableStyleProperty(cssProp);
4594
+ }
4595
+ return true;
4596
+ }
4364
4597
  matchesElement(_element, _selector) {
4365
4598
  // This method is deprecated and no longer in use so we return false.
4366
4599
  return false;
@@ -4385,18 +4618,17 @@ class WebAnimationsDriver {
4385
4618
  if (easing) {
4386
4619
  playerOptions['easing'] = easing;
4387
4620
  }
4388
- const previousStyles = {};
4621
+ const previousStyles = new Map();
4389
4622
  const previousWebAnimationPlayers = previousPlayers.filter(player => player instanceof WebAnimationsPlayer);
4390
4623
  if (allowPreviousPlayerStylesMerge(duration, delay)) {
4391
4624
  previousWebAnimationPlayers.forEach(player => {
4392
- let styles = player.currentSnapshot;
4393
- Object.keys(styles).forEach(prop => previousStyles[prop] = styles[prop]);
4625
+ player.currentSnapshot.forEach((val, prop) => previousStyles.set(prop, val));
4394
4626
  });
4395
4627
  }
4396
- keyframes = keyframes.map(styles => copyStyles(styles, false));
4397
- keyframes = balancePreviousStylesIntoKeyframes(element, keyframes, previousStyles);
4398
- const specialStyles = packageNonAnimatableStyles(element, keyframes);
4399
- return new WebAnimationsPlayer(element, keyframes, playerOptions, specialStyles);
4628
+ let _keyframes = normalizeKeyframes(keyframes).map(styles => copyStyles(styles));
4629
+ _keyframes = balancePreviousStylesIntoKeyframes(element, _keyframes, previousStyles);
4630
+ const specialStyles = packageNonAnimatableStyles(element, _keyframes);
4631
+ return new WebAnimationsPlayer(element, _keyframes, playerOptions, specialStyles);
4400
4632
  }
4401
4633
  }
4402
4634
 
@@ -4436,5 +4668,5 @@ class WebAnimationsDriver {
4436
4668
  * Generated bundle index. Do not edit.
4437
4669
  */
4438
4670
 
4439
- export { AnimationDriver, Animation as ɵAnimation, AnimationEngine as ɵAnimationEngine, AnimationStyleNormalizer as ɵAnimationStyleNormalizer, NoopAnimationDriver as ɵNoopAnimationDriver, NoopAnimationStyleNormalizer as ɵNoopAnimationStyleNormalizer, WebAnimationsDriver as ɵWebAnimationsDriver, WebAnimationsPlayer as ɵWebAnimationsPlayer, WebAnimationsStyleNormalizer as ɵWebAnimationsStyleNormalizer, allowPreviousPlayerStylesMerge as ɵallowPreviousPlayerStylesMerge, containsElement as ɵcontainsElement, getParentElement as ɵgetParentElement, invokeQuery as ɵinvokeQuery, validateStyleProperty as ɵvalidateStyleProperty };
4671
+ export { AnimationDriver, Animation as ɵAnimation, AnimationEngine as ɵAnimationEngine, AnimationStyleNormalizer as ɵAnimationStyleNormalizer, NoopAnimationDriver as ɵNoopAnimationDriver, NoopAnimationStyleNormalizer as ɵNoopAnimationStyleNormalizer, WebAnimationsDriver as ɵWebAnimationsDriver, WebAnimationsPlayer as ɵWebAnimationsPlayer, WebAnimationsStyleNormalizer as ɵWebAnimationsStyleNormalizer, allowPreviousPlayerStylesMerge as ɵallowPreviousPlayerStylesMerge, containsElement as ɵcontainsElement, getParentElement as ɵgetParentElement, invokeQuery as ɵinvokeQuery, normalizeKeyframes as ɵnormalizeKeyframes, validateStyleProperty as ɵvalidateStyleProperty };
4440
4672
  //# sourceMappingURL=browser.mjs.map