@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,12 +2458,14 @@ 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 === null || stateName === void 0 ? void 0 : 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) {
2468
+ var _a;
2218
2469
  const errors = [];
2219
2470
  const transitionAnimationParams = this.ast.options && this.ast.options.params || EMPTY_OBJECT;
2220
2471
  const currentAnimationParams = currentOptions && currentOptions.params || EMPTY_OBJECT;
@@ -2225,7 +2476,10 @@ class AnimationTransitionFactory {
2225
2476
  const preStyleMap = new Map();
2226
2477
  const postStyleMap = new Map();
2227
2478
  const isRemoval = nextState === 'void';
2228
- const animationOptions = { params: Object.assign(Object.assign({}, transitionAnimationParams), nextAnimationParams) };
2479
+ const animationOptions = {
2480
+ params: applyParamDefaults(nextAnimationParams, transitionAnimationParams),
2481
+ delay: (_a = this.ast.options) === null || _a === void 0 ? void 0 : _a.delay,
2482
+ };
2229
2483
  const timelines = skipAstBuild ?
2230
2484
  [] :
2231
2485
  buildAnimationTimelines(driver, element, this.ast.animation, enterClassName, leaveClassName, currentStateStyles, nextStateStyles, animationOptions, subInstructions, errors);
@@ -2238,10 +2492,10 @@ class AnimationTransitionFactory {
2238
2492
  }
2239
2493
  timelines.forEach(tl => {
2240
2494
  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);
2495
+ const preProps = getOrSetDefaultValue(preStyleMap, elm, new Set());
2496
+ tl.preStyleProps.forEach(prop => preProps.add(prop));
2497
+ const postProps = getOrSetDefaultValue(postStyleMap, elm, new Set());
2498
+ tl.postStyleProps.forEach(prop => postProps.add(prop));
2245
2499
  if (elm !== element) {
2246
2500
  queriedElements.add(elm);
2247
2501
  }
@@ -2253,6 +2507,15 @@ class AnimationTransitionFactory {
2253
2507
  function oneOrMoreTransitionsMatch(matchFns, currentState, nextState, element, params) {
2254
2508
  return matchFns.some(fn => fn(currentState, nextState, element, params));
2255
2509
  }
2510
+ function applyParamDefaults(userParams, defaults) {
2511
+ const result = copyObj(defaults);
2512
+ for (const key in userParams) {
2513
+ if (userParams.hasOwnProperty(key) && userParams[key] != null) {
2514
+ result[key] = userParams[key];
2515
+ }
2516
+ }
2517
+ return result;
2518
+ }
2256
2519
  class AnimationStateStyles {
2257
2520
  constructor(styles, defaultParams, normalizer) {
2258
2521
  this.styles = styles;
@@ -2260,25 +2523,23 @@ class AnimationStateStyles {
2260
2523
  this.normalizer = normalizer;
2261
2524
  }
2262
2525
  buildStyles(params, errors) {
2263
- const finalStyles = {};
2526
+ const finalStyles = new Map();
2264
2527
  const combinedParams = copyObj(this.defaultParams);
2265
2528
  Object.keys(params).forEach(key => {
2266
2529
  const value = params[key];
2267
- if (value != null) {
2530
+ if (value !== null) {
2268
2531
  combinedParams[key] = value;
2269
2532
  }
2270
2533
  });
2271
2534
  this.styles.styles.forEach(value => {
2272
2535
  if (typeof value !== 'string') {
2273
- const styleObj = value;
2274
- Object.keys(styleObj).forEach(prop => {
2275
- let val = styleObj[prop];
2276
- if (val.length > 1) {
2536
+ value.forEach((val, prop) => {
2537
+ if (val) {
2277
2538
  val = interpolateParams(val, combinedParams, errors);
2278
2539
  }
2279
2540
  const normalizedProp = this.normalizer.normalizePropertyName(prop, errors);
2280
2541
  val = this.normalizer.normalizeStyleValue(prop, normalizedProp, val, errors);
2281
- finalStyles[normalizedProp] = val;
2542
+ finalStyles.set(normalizedProp, val);
2282
2543
  });
2283
2544
  }
2284
2545
  });
@@ -2295,10 +2556,10 @@ class AnimationTrigger {
2295
2556
  this.ast = ast;
2296
2557
  this._normalizer = _normalizer;
2297
2558
  this.transitionFactories = [];
2298
- this.states = {};
2559
+ this.states = new Map();
2299
2560
  ast.states.forEach(ast => {
2300
2561
  const defaultParams = (ast.options && ast.options.params) || {};
2301
- this.states[ast.name] = new AnimationStateStyles(ast.style, defaultParams, _normalizer);
2562
+ this.states.set(ast.name, new AnimationStateStyles(ast.style, defaultParams, _normalizer));
2302
2563
  });
2303
2564
  balanceProperties(this.states, 'true', '1');
2304
2565
  balanceProperties(this.states, 'false', '0');
@@ -2331,14 +2592,14 @@ function createFallbackTransition(triggerName, states, normalizer) {
2331
2592
  };
2332
2593
  return new AnimationTransitionFactory(triggerName, transition, states);
2333
2594
  }
2334
- function balanceProperties(obj, key1, key2) {
2335
- if (obj.hasOwnProperty(key1)) {
2336
- if (!obj.hasOwnProperty(key2)) {
2337
- obj[key2] = obj[key1];
2595
+ function balanceProperties(stateMap, key1, key2) {
2596
+ if (stateMap.has(key1)) {
2597
+ if (!stateMap.has(key2)) {
2598
+ stateMap.set(key2, stateMap.get(key1));
2338
2599
  }
2339
2600
  }
2340
- else if (obj.hasOwnProperty(key2)) {
2341
- obj[key1] = obj[key2];
2601
+ else if (stateMap.has(key2)) {
2602
+ stateMap.set(key1, stateMap.get(key2));
2342
2603
  }
2343
2604
  }
2344
2605
 
@@ -2355,8 +2616,8 @@ class TimelineAnimationEngine {
2355
2616
  this.bodyNode = bodyNode;
2356
2617
  this._driver = _driver;
2357
2618
  this._normalizer = _normalizer;
2358
- this._animations = {};
2359
- this._playersById = {};
2619
+ this._animations = new Map();
2620
+ this._playersById = new Map();
2360
2621
  this.players = [];
2361
2622
  }
2362
2623
  register(id, metadata) {
@@ -2370,24 +2631,24 @@ class TimelineAnimationEngine {
2370
2631
  if (warnings.length) {
2371
2632
  warnRegister(warnings);
2372
2633
  }
2373
- this._animations[id] = ast;
2634
+ this._animations.set(id, ast);
2374
2635
  }
2375
2636
  }
2376
2637
  _buildPlayer(i, preStyles, postStyles) {
2377
2638
  const element = i.element;
2378
- const keyframes = normalizeKeyframes(this._driver, this._normalizer, element, i.keyframes, preStyles, postStyles);
2639
+ const keyframes = normalizeKeyframes$1(this._driver, this._normalizer, element, i.keyframes, preStyles, postStyles);
2379
2640
  return this._driver.animate(element, keyframes, i.duration, i.delay, i.easing, [], true);
2380
2641
  }
2381
2642
  create(id, element, options = {}) {
2382
2643
  const errors = [];
2383
- const ast = this._animations[id];
2644
+ const ast = this._animations.get(id);
2384
2645
  let instructions;
2385
2646
  const autoStylesMap = new Map();
2386
2647
  if (ast) {
2387
- instructions = buildAnimationTimelines(this._driver, element, ast, ENTER_CLASSNAME, LEAVE_CLASSNAME, {}, {}, options, EMPTY_INSTRUCTION_MAP, errors);
2648
+ instructions = buildAnimationTimelines(this._driver, element, ast, ENTER_CLASSNAME, LEAVE_CLASSNAME, new Map(), new Map(), options, EMPTY_INSTRUCTION_MAP, errors);
2388
2649
  instructions.forEach(inst => {
2389
- const styles = getOrSetAsInMap(autoStylesMap, inst.element, {});
2390
- inst.postStyleProps.forEach(prop => styles[prop] = null);
2650
+ const styles = getOrSetDefaultValue(autoStylesMap, inst.element, new Map());
2651
+ inst.postStyleProps.forEach(prop => styles.set(prop, null));
2391
2652
  });
2392
2653
  }
2393
2654
  else {
@@ -2398,16 +2659,16 @@ class TimelineAnimationEngine {
2398
2659
  throw createAnimationFailed(errors);
2399
2660
  }
2400
2661
  autoStylesMap.forEach((styles, element) => {
2401
- Object.keys(styles).forEach(prop => {
2402
- styles[prop] = this._driver.computeStyle(element, prop, AUTO_STYLE);
2662
+ styles.forEach((_, prop) => {
2663
+ styles.set(prop, this._driver.computeStyle(element, prop, AUTO_STYLE));
2403
2664
  });
2404
2665
  });
2405
2666
  const players = instructions.map(i => {
2406
2667
  const styles = autoStylesMap.get(i.element);
2407
- return this._buildPlayer(i, {}, styles);
2668
+ return this._buildPlayer(i, new Map(), styles);
2408
2669
  });
2409
2670
  const player = optimizeGroupPlayer(players);
2410
- this._playersById[id] = player;
2671
+ this._playersById.set(id, player);
2411
2672
  player.onDestroy(() => this.destroy(id));
2412
2673
  this.players.push(player);
2413
2674
  return player;
@@ -2415,14 +2676,14 @@ class TimelineAnimationEngine {
2415
2676
  destroy(id) {
2416
2677
  const player = this._getPlayer(id);
2417
2678
  player.destroy();
2418
- delete this._playersById[id];
2679
+ this._playersById.delete(id);
2419
2680
  const index = this.players.indexOf(player);
2420
2681
  if (index >= 0) {
2421
2682
  this.players.splice(index, 1);
2422
2683
  }
2423
2684
  }
2424
2685
  _getPlayer(id) {
2425
- const player = this._playersById[id];
2686
+ const player = this._playersById.get(id);
2426
2687
  if (!player) {
2427
2688
  throw missingPlayer(id);
2428
2689
  }
@@ -2544,14 +2805,14 @@ class AnimationTransitionNamespace {
2544
2805
  this.hostElement = hostElement;
2545
2806
  this._engine = _engine;
2546
2807
  this.players = [];
2547
- this._triggers = {};
2808
+ this._triggers = new Map();
2548
2809
  this._queue = [];
2549
2810
  this._elementListeners = new Map();
2550
2811
  this._hostClassName = 'ng-tns-' + id;
2551
2812
  addClass(hostElement, this._hostClassName);
2552
2813
  }
2553
2814
  listen(element, name, phase, callback) {
2554
- if (!this._triggers.hasOwnProperty(name)) {
2815
+ if (!this._triggers.has(name)) {
2555
2816
  throw missingTrigger(phase, name);
2556
2817
  }
2557
2818
  if (phase == null || phase.length == 0) {
@@ -2560,14 +2821,14 @@ class AnimationTransitionNamespace {
2560
2821
  if (!isTriggerEventValid(phase)) {
2561
2822
  throw unsupportedTriggerEvent(phase, name);
2562
2823
  }
2563
- const listeners = getOrSetAsInMap(this._elementListeners, element, []);
2824
+ const listeners = getOrSetDefaultValue(this._elementListeners, element, []);
2564
2825
  const data = { name, phase, callback };
2565
2826
  listeners.push(data);
2566
- const triggersWithStates = getOrSetAsInMap(this._engine.statesByElement, element, {});
2567
- if (!triggersWithStates.hasOwnProperty(name)) {
2827
+ const triggersWithStates = getOrSetDefaultValue(this._engine.statesByElement, element, new Map());
2828
+ if (!triggersWithStates.has(name)) {
2568
2829
  addClass(element, NG_TRIGGER_CLASSNAME);
2569
2830
  addClass(element, NG_TRIGGER_CLASSNAME + '-' + name);
2570
- triggersWithStates[name] = DEFAULT_STATE_VALUE;
2831
+ triggersWithStates.set(name, DEFAULT_STATE_VALUE);
2571
2832
  }
2572
2833
  return () => {
2573
2834
  // the event listener is removed AFTER the flush has occurred such
@@ -2578,24 +2839,24 @@ class AnimationTransitionNamespace {
2578
2839
  if (index >= 0) {
2579
2840
  listeners.splice(index, 1);
2580
2841
  }
2581
- if (!this._triggers[name]) {
2582
- delete triggersWithStates[name];
2842
+ if (!this._triggers.has(name)) {
2843
+ triggersWithStates.delete(name);
2583
2844
  }
2584
2845
  });
2585
2846
  };
2586
2847
  }
2587
2848
  register(name, ast) {
2588
- if (this._triggers[name]) {
2849
+ if (this._triggers.has(name)) {
2589
2850
  // throw
2590
2851
  return false;
2591
2852
  }
2592
2853
  else {
2593
- this._triggers[name] = ast;
2854
+ this._triggers.set(name, ast);
2594
2855
  return true;
2595
2856
  }
2596
2857
  }
2597
2858
  _getTrigger(name) {
2598
- const trigger = this._triggers[name];
2859
+ const trigger = this._triggers.get(name);
2599
2860
  if (!trigger) {
2600
2861
  throw unregisteredTrigger(name);
2601
2862
  }
@@ -2608,15 +2869,15 @@ class AnimationTransitionNamespace {
2608
2869
  if (!triggersWithStates) {
2609
2870
  addClass(element, NG_TRIGGER_CLASSNAME);
2610
2871
  addClass(element, NG_TRIGGER_CLASSNAME + '-' + triggerName);
2611
- this._engine.statesByElement.set(element, triggersWithStates = {});
2872
+ this._engine.statesByElement.set(element, triggersWithStates = new Map());
2612
2873
  }
2613
- let fromState = triggersWithStates[triggerName];
2874
+ let fromState = triggersWithStates.get(triggerName);
2614
2875
  const toState = new StateValue(value, this.id);
2615
2876
  const isObj = value && value.hasOwnProperty('value');
2616
2877
  if (!isObj && fromState) {
2617
2878
  toState.absorbOptions(fromState.options);
2618
2879
  }
2619
- triggersWithStates[triggerName] = toState;
2880
+ triggersWithStates.set(triggerName, toState);
2620
2881
  if (!fromState) {
2621
2882
  fromState = DEFAULT_STATE_VALUE;
2622
2883
  }
@@ -2646,7 +2907,7 @@ class AnimationTransitionNamespace {
2646
2907
  }
2647
2908
  return;
2648
2909
  }
2649
- const playersOnElement = getOrSetAsInMap(this._engine.playersByElement, element, []);
2910
+ const playersOnElement = getOrSetDefaultValue(this._engine.playersByElement, element, []);
2650
2911
  playersOnElement.forEach(player => {
2651
2912
  // only remove the player if it is queued on the EXACT same trigger/namespace
2652
2913
  // we only also deal with queued players here because if the animation has
@@ -2690,10 +2951,8 @@ class AnimationTransitionNamespace {
2690
2951
  return player;
2691
2952
  }
2692
2953
  deregister(name) {
2693
- delete this._triggers[name];
2694
- this._engine.statesByElement.forEach((stateMap, element) => {
2695
- delete stateMap[name];
2696
- });
2954
+ this._triggers.delete(name);
2955
+ this._engine.statesByElement.forEach(stateMap => stateMap.delete(name));
2697
2956
  this._elementListeners.forEach((listeners, element) => {
2698
2957
  this._elementListeners.set(element, listeners.filter(entry => {
2699
2958
  return entry.name != name;
@@ -2736,11 +2995,11 @@ class AnimationTransitionNamespace {
2736
2995
  const previousTriggersValues = new Map();
2737
2996
  if (triggerStates) {
2738
2997
  const players = [];
2739
- Object.keys(triggerStates).forEach(triggerName => {
2740
- previousTriggersValues.set(triggerName, triggerStates[triggerName].value);
2998
+ triggerStates.forEach((state, triggerName) => {
2999
+ previousTriggersValues.set(triggerName, state.value);
2741
3000
  // this check is here in the event that an element is removed
2742
3001
  // twice (both on the host level and the component level)
2743
- if (this._triggers[triggerName]) {
3002
+ if (this._triggers.has(triggerName)) {
2744
3003
  const player = this.trigger(element, triggerName, VOID_VALUE, defaultToFallback);
2745
3004
  if (player) {
2746
3005
  players.push(player);
@@ -2769,9 +3028,9 @@ class AnimationTransitionNamespace {
2769
3028
  if (visitedTriggers.has(triggerName))
2770
3029
  return;
2771
3030
  visitedTriggers.add(triggerName);
2772
- const trigger = this._triggers[triggerName];
3031
+ const trigger = this._triggers.get(triggerName);
2773
3032
  const transition = trigger.fallbackTransition;
2774
- const fromState = elementStates[triggerName] || DEFAULT_STATE_VALUE;
3033
+ const fromState = elementStates.get(triggerName) || DEFAULT_STATE_VALUE;
2775
3034
  const toState = new StateValue(VOID_VALUE);
2776
3035
  const player = new TransitionAnimationPlayer(this.id, triggerName, element);
2777
3036
  this._engine.totalQueuedPlayers++;
@@ -2958,35 +3217,20 @@ class TransitionAnimationEngine {
2958
3217
  const limit = namespaceList.length - 1;
2959
3218
  if (limit >= 0) {
2960
3219
  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
- }
3220
+ // Find the closest ancestor with an existing namespace so we can then insert `ns` after it,
3221
+ // establishing a top-down ordering of namespaces in `this._namespaceList`.
3222
+ let ancestor = this.driver.getParentElement(hostElement);
3223
+ while (ancestor) {
3224
+ const ancestorNs = namespacesByHostElement.get(ancestor);
3225
+ if (ancestorNs) {
3226
+ // An animation namespace has been registered for this ancestor, so we insert `ns`
3227
+ // right after it to establish top-down ordering of animation namespaces.
3228
+ const index = namespaceList.indexOf(ancestorNs);
3229
+ namespaceList.splice(index + 1, 0, ns);
3230
+ found = true;
3231
+ break;
2989
3232
  }
3233
+ ancestor = this.driver.getParentElement(ancestor);
2990
3234
  }
2991
3235
  if (!found) {
2992
3236
  // No namespace exists that is an ancestor of `ns`, so `ns` is inserted at the front to
@@ -3040,11 +3284,9 @@ class TransitionAnimationEngine {
3040
3284
  const namespaces = new Set();
3041
3285
  const elementStates = this.statesByElement.get(element);
3042
3286
  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);
3287
+ for (let stateValue of elementStates.values()) {
3288
+ if (stateValue.namespaceId) {
3289
+ const ns = this._fetchNamespace(stateValue.namespaceId);
3048
3290
  if (ns) {
3049
3291
  namespaces.add(ns);
3050
3292
  }
@@ -3352,8 +3594,10 @@ class TransitionAnimationEngine {
3352
3594
  // we need to restore the previous trigger value since the element has
3353
3595
  // only been moved and hasn't actually left the DOM
3354
3596
  const triggersWithStates = this.statesByElement.get(entry.element);
3355
- if (triggersWithStates && triggersWithStates[entry.triggerName]) {
3356
- triggersWithStates[entry.triggerName].value = previousValue;
3597
+ if (triggersWithStates && triggersWithStates.has(entry.triggerName)) {
3598
+ const state = triggersWithStates.get(entry.triggerName);
3599
+ state.value = previousValue;
3600
+ triggersWithStates.set(entry.triggerName, state);
3357
3601
  }
3358
3602
  }
3359
3603
  player.destroy();
@@ -3403,24 +3647,22 @@ class TransitionAnimationEngine {
3403
3647
  subTimelines.append(element, instruction.timelines);
3404
3648
  const tuple = { instruction, player, element };
3405
3649
  queuedInstructions.push(tuple);
3406
- instruction.queriedElements.forEach(element => getOrSetAsInMap(queriedElements, element, []).push(player));
3650
+ instruction.queriedElements.forEach(element => getOrSetDefaultValue(queriedElements, element, []).push(player));
3407
3651
  instruction.preStyleProps.forEach((stringMap, element) => {
3408
- const props = Object.keys(stringMap);
3409
- if (props.length) {
3652
+ if (stringMap.size) {
3410
3653
  let setVal = allPreStyleElements.get(element);
3411
3654
  if (!setVal) {
3412
3655
  allPreStyleElements.set(element, setVal = new Set());
3413
3656
  }
3414
- props.forEach(prop => setVal.add(prop));
3657
+ stringMap.forEach((_, prop) => setVal.add(prop));
3415
3658
  }
3416
3659
  });
3417
3660
  instruction.postStyleProps.forEach((stringMap, element) => {
3418
- const props = Object.keys(stringMap);
3419
3661
  let setVal = allPostStyleElements.get(element);
3420
3662
  if (!setVal) {
3421
3663
  allPostStyleElements.set(element, setVal = new Set());
3422
3664
  }
3423
- props.forEach(prop => setVal.add(prop));
3665
+ stringMap.forEach((_, prop) => setVal.add(prop));
3424
3666
  });
3425
3667
  });
3426
3668
  }
@@ -3449,7 +3691,7 @@ class TransitionAnimationEngine {
3449
3691
  const element = player.element;
3450
3692
  const previousPlayers = this._getPreviousPlayers(element, false, player.namespaceId, player.triggerName, null);
3451
3693
  previousPlayers.forEach(prevPlayer => {
3452
- getOrSetAsInMap(allPreviousPlayersMap, element, []).push(prevPlayer);
3694
+ getOrSetDefaultValue(allPreviousPlayersMap, element, []).push(prevPlayer);
3453
3695
  prevPlayer.destroy();
3454
3696
  });
3455
3697
  });
@@ -3477,9 +3719,10 @@ class TransitionAnimationEngine {
3477
3719
  cloakAndComputeStyles(preStylesMap, this.driver, new Set(nodes), allPreStyleElements, ɵPRE_STYLE);
3478
3720
  });
3479
3721
  replaceNodes.forEach(node => {
3722
+ var _a, _b;
3480
3723
  const post = postStylesMap.get(node);
3481
3724
  const pre = preStylesMap.get(node);
3482
- postStylesMap.set(node, Object.assign(Object.assign({}, post), pre));
3725
+ postStylesMap.set(node, new Map([...Array.from((_a = post === null || post === void 0 ? void 0 : post.entries()) !== null && _a !== void 0 ? _a : []), ...Array.from((_b = pre === null || pre === void 0 ? void 0 : pre.entries()) !== null && _b !== void 0 ? _b : [])]));
3483
3726
  });
3484
3727
  const rootPlayers = [];
3485
3728
  const subPlayers = [];
@@ -3673,7 +3916,7 @@ class TransitionAnimationEngine {
3673
3916
  for (const timelineInstruction of instruction.timelines) {
3674
3917
  const element = timelineInstruction.element;
3675
3918
  const isQueriedElement = element !== rootElement;
3676
- const players = getOrSetAsInMap(allPreviousPlayersMap, element, []);
3919
+ const players = getOrSetDefaultValue(allPreviousPlayersMap, element, []);
3677
3920
  const previousPlayers = this._getPreviousPlayers(element, isQueriedElement, targetNameSpaceId, targetTriggerName, instruction.toState);
3678
3921
  previousPlayers.forEach(player => {
3679
3922
  const realPlayer = player.getRealPlayer();
@@ -3716,7 +3959,7 @@ class TransitionAnimationEngine {
3716
3959
  });
3717
3960
  const preStyles = preStylesMap.get(element);
3718
3961
  const postStyles = postStylesMap.get(element);
3719
- const keyframes = normalizeKeyframes(this.driver, this._normalizer, element, timelineInstruction.keyframes, preStyles, postStyles);
3962
+ const keyframes = normalizeKeyframes$1(this.driver, this._normalizer, element, timelineInstruction.keyframes, preStyles, postStyles);
3720
3963
  const player = this._buildPlayer(timelineInstruction, keyframes, previousPlayers);
3721
3964
  // this means that this particular player belongs to a sub trigger. It is
3722
3965
  // important that we match this player up with the corresponding (@trigger.listener)
@@ -3731,7 +3974,7 @@ class TransitionAnimationEngine {
3731
3974
  return player;
3732
3975
  });
3733
3976
  allQueriedPlayers.forEach(player => {
3734
- getOrSetAsInMap(this.playersByQueriedElement, player.element, []).push(player);
3977
+ getOrSetDefaultValue(this.playersByQueriedElement, player.element, []).push(player);
3735
3978
  player.onDone(() => deleteOrUnsetInMap(this.playersByQueriedElement, player.element, player));
3736
3979
  });
3737
3980
  allConsumedElements.forEach(element => addClass(element, NG_ANIMATING_CLASSNAME));
@@ -3743,7 +3986,7 @@ class TransitionAnimationEngine {
3743
3986
  // this basically makes all of the callbacks for sub element animations
3744
3987
  // be dependent on the upper players for when they finish
3745
3988
  allSubElements.forEach(element => {
3746
- getOrSetAsInMap(skippedPlayersMap, element, []).push(player);
3989
+ getOrSetDefaultValue(skippedPlayersMap, element, []).push(player);
3747
3990
  });
3748
3991
  return player;
3749
3992
  }
@@ -3763,7 +4006,7 @@ class TransitionAnimationPlayer {
3763
4006
  this.element = element;
3764
4007
  this._player = new NoopAnimationPlayer();
3765
4008
  this._containsRealPlayer = false;
3766
- this._queuedCallbacks = {};
4009
+ this._queuedCallbacks = new Map();
3767
4010
  this.destroyed = false;
3768
4011
  this.markedForDestroy = false;
3769
4012
  this.disabled = false;
@@ -3774,10 +4017,10 @@ class TransitionAnimationPlayer {
3774
4017
  if (this._containsRealPlayer)
3775
4018
  return;
3776
4019
  this._player = player;
3777
- Object.keys(this._queuedCallbacks).forEach(phase => {
3778
- this._queuedCallbacks[phase].forEach(callback => listenOnPlayer(player, phase, undefined, callback));
4020
+ this._queuedCallbacks.forEach((callbacks, phase) => {
4021
+ callbacks.forEach(callback => listenOnPlayer(player, phase, undefined, callback));
3779
4022
  });
3780
- this._queuedCallbacks = {};
4023
+ this._queuedCallbacks.clear();
3781
4024
  this._containsRealPlayer = true;
3782
4025
  this.overrideTotalTime(player.totalTime);
3783
4026
  this.queued = false;
@@ -3797,7 +4040,7 @@ class TransitionAnimationPlayer {
3797
4040
  player.onDestroy(() => this.destroy());
3798
4041
  }
3799
4042
  _queueEvent(name, callback) {
3800
- getOrSetAsInMap(this._queuedCallbacks, name, []).push(callback);
4043
+ getOrSetDefaultValue(this._queuedCallbacks, name, []).push(callback);
3801
4044
  }
3802
4045
  onDone(fn) {
3803
4046
  if (this.queued) {
@@ -3859,29 +4102,14 @@ class TransitionAnimationPlayer {
3859
4102
  }
3860
4103
  }
3861
4104
  function deleteOrUnsetInMap(map, key, value) {
3862
- let currentValues;
3863
- if (map instanceof Map) {
3864
- currentValues = map.get(key);
3865
- if (currentValues) {
3866
- if (currentValues.length) {
3867
- const index = currentValues.indexOf(value);
3868
- currentValues.splice(index, 1);
3869
- }
3870
- if (currentValues.length == 0) {
3871
- map.delete(key);
3872
- }
4105
+ let currentValues = map.get(key);
4106
+ if (currentValues) {
4107
+ if (currentValues.length) {
4108
+ const index = currentValues.indexOf(value);
4109
+ currentValues.splice(index, 1);
3873
4110
  }
3874
- }
3875
- else {
3876
- currentValues = map[key];
3877
- if (currentValues) {
3878
- if (currentValues.length) {
3879
- const index = currentValues.indexOf(value);
3880
- currentValues.splice(index, 1);
3881
- }
3882
- if (currentValues.length == 0) {
3883
- delete map[key];
3884
- }
4111
+ if (currentValues.length == 0) {
4112
+ map.delete(key);
3885
4113
  }
3886
4114
  }
3887
4115
  return currentValues;
@@ -3908,9 +4136,10 @@ function cloakAndComputeStyles(valuesMap, driver, elements, elementPropsMap, def
3908
4136
  elements.forEach(element => cloakVals.push(cloakElement(element)));
3909
4137
  const failedElements = [];
3910
4138
  elementPropsMap.forEach((props, element) => {
3911
- const styles = {};
4139
+ const styles = new Map();
3912
4140
  props.forEach(prop => {
3913
- const value = styles[prop] = driver.computeStyle(element, prop, defaultStyle);
4141
+ const value = driver.computeStyle(element, prop, defaultStyle);
4142
+ styles.set(prop, value);
3914
4143
  // there is no easy way to detect this because a sub element could be removed
3915
4144
  // by a parent animation element being detached.
3916
4145
  if (!value || value.length == 0) {
@@ -4100,13 +4329,6 @@ class AnimationEngine {
4100
4329
  }
4101
4330
  }
4102
4331
 
4103
- /**
4104
- * @license
4105
- * Copyright Google LLC All Rights Reserved.
4106
- *
4107
- * Use of this source code is governed by an MIT-style license that can be
4108
- * found in the LICENSE file at https://angular.io/license
4109
- */
4110
4332
  /**
4111
4333
  * Returns an instance of `SpecialCasedStyles` if and when any special (non animateable) styles are
4112
4334
  * detected.
@@ -4127,7 +4349,7 @@ function packageNonAnimatableStyles(element, styles) {
4127
4349
  endStyles = filterNonAnimatableStyles(styles[styles.length - 1]);
4128
4350
  }
4129
4351
  }
4130
- else if (styles) {
4352
+ else if (styles instanceof Map) {
4131
4353
  startStyles = filterNonAnimatableStyles(styles);
4132
4354
  }
4133
4355
  return (startStyles || endStyles) ? new SpecialCasedStyles(element, startStyles, endStyles) :
@@ -4149,7 +4371,7 @@ class SpecialCasedStyles {
4149
4371
  this._state = 0 /* Pending */;
4150
4372
  let initialStyles = SpecialCasedStyles.initialStylesByElement.get(_element);
4151
4373
  if (!initialStyles) {
4152
- SpecialCasedStyles.initialStylesByElement.set(_element, initialStyles = {});
4374
+ SpecialCasedStyles.initialStylesByElement.set(_element, initialStyles = new Map());
4153
4375
  }
4154
4376
  this._initialStyles = initialStyles;
4155
4377
  }
@@ -4192,14 +4414,12 @@ class SpecialCasedStyles {
4192
4414
  SpecialCasedStyles.initialStylesByElement = ( /* @__PURE__ */new WeakMap());
4193
4415
  function filterNonAnimatableStyles(styles) {
4194
4416
  let result = null;
4195
- const props = Object.keys(styles);
4196
- for (let i = 0; i < props.length; i++) {
4197
- const prop = props[i];
4417
+ styles.forEach((val, prop) => {
4198
4418
  if (isNonAnimatableStyle(prop)) {
4199
- result = result || {};
4200
- result[prop] = styles[prop];
4419
+ result = result || new Map();
4420
+ result.set(prop, val);
4201
4421
  }
4202
- }
4422
+ });
4203
4423
  return result;
4204
4424
  }
4205
4425
  function isNonAnimatableStyle(prop) {
@@ -4221,7 +4441,7 @@ class WebAnimationsPlayer {
4221
4441
  this._destroyed = false;
4222
4442
  this.time = 0;
4223
4443
  this.parentPlayer = null;
4224
- this.currentSnapshot = {};
4444
+ this.currentSnapshot = new Map();
4225
4445
  this._duration = options['duration'];
4226
4446
  this._delay = options['delay'] || 0;
4227
4447
  this.time = this._duration + this._delay;
@@ -4244,7 +4464,7 @@ class WebAnimationsPlayer {
4244
4464
  const keyframes = this.keyframes;
4245
4465
  this.domPlayer =
4246
4466
  this._triggerWebAnimation(this.element, keyframes, this.options);
4247
- this._finalKeyframe = keyframes.length ? keyframes[keyframes.length - 1] : {};
4467
+ this._finalKeyframe = keyframes.length ? keyframes[keyframes.length - 1] : new Map();
4248
4468
  this.domPlayer.addEventListener('finish', () => this._onFinish());
4249
4469
  }
4250
4470
  _preparePlayerBeforeStart() {
@@ -4256,11 +4476,18 @@ class WebAnimationsPlayer {
4256
4476
  this.domPlayer.pause();
4257
4477
  }
4258
4478
  }
4479
+ _convertKeyframesToObject(keyframes) {
4480
+ const kfs = [];
4481
+ keyframes.forEach(frame => {
4482
+ kfs.push(Object.fromEntries(frame));
4483
+ });
4484
+ return kfs;
4485
+ }
4259
4486
  /** @internal */
4260
4487
  _triggerWebAnimation(element, keyframes, options) {
4261
4488
  // jscompiler doesn't seem to know animate is a native property because it's not fully
4262
4489
  // supported yet across common browsers (we polyfill it for Edge/Safari) [CL #143630929]
4263
- return element['animate'](keyframes, options);
4490
+ return element['animate'](this._convertKeyframesToObject(keyframes), options);
4264
4491
  }
4265
4492
  onStart(fn) {
4266
4493
  this._onStartFns.push(fn);
@@ -4338,15 +4565,15 @@ class WebAnimationsPlayer {
4338
4565
  return this._delay + this._duration;
4339
4566
  }
4340
4567
  beforeDestroy() {
4341
- const styles = {};
4568
+ const styles = new Map();
4342
4569
  if (this.hasStarted()) {
4343
4570
  // note: this code is invoked only when the `play` function was called prior to this
4344
4571
  // (thus `hasStarted` returns true), this implies that the code that initializes
4345
4572
  // `_finalKeyframe` has also been executed and the non-null assertion can be safely used here
4346
4573
  const finalKeyframe = this._finalKeyframe;
4347
- Object.keys(finalKeyframe).forEach(prop => {
4348
- if (prop != 'offset') {
4349
- styles[prop] = this._finished ? finalKeyframe[prop] : computeStyle(this.element, prop);
4574
+ finalKeyframe.forEach((val, prop) => {
4575
+ if (prop !== 'offset') {
4576
+ styles.set(prop, this._finished ? val : computeStyle(this.element, prop));
4350
4577
  }
4351
4578
  });
4352
4579
  }
@@ -4354,7 +4581,7 @@ class WebAnimationsPlayer {
4354
4581
  }
4355
4582
  /** @internal */
4356
4583
  triggerCallback(phaseName) {
4357
- const methods = phaseName == 'start' ? this._onStartFns : this._onDoneFns;
4584
+ const methods = phaseName === 'start' ? this._onStartFns : this._onDoneFns;
4358
4585
  methods.forEach(fn => fn());
4359
4586
  methods.length = 0;
4360
4587
  }
@@ -4364,6 +4591,14 @@ class WebAnimationsDriver {
4364
4591
  validateStyleProperty(prop) {
4365
4592
  return validateStyleProperty(prop);
4366
4593
  }
4594
+ validateAnimatableStyleProperty(prop) {
4595
+ // Perform actual validation in dev mode only, in prod mode this check is a noop.
4596
+ if (ngDevMode) {
4597
+ const cssProp = camelCaseToDashCase(prop);
4598
+ return validateWebAnimatableStyleProperty(cssProp);
4599
+ }
4600
+ return true;
4601
+ }
4367
4602
  matchesElement(_element, _selector) {
4368
4603
  // This method is deprecated and no longer in use so we return false.
4369
4604
  return false;
@@ -4388,18 +4623,17 @@ class WebAnimationsDriver {
4388
4623
  if (easing) {
4389
4624
  playerOptions['easing'] = easing;
4390
4625
  }
4391
- const previousStyles = {};
4626
+ const previousStyles = new Map();
4392
4627
  const previousWebAnimationPlayers = previousPlayers.filter(player => player instanceof WebAnimationsPlayer);
4393
4628
  if (allowPreviousPlayerStylesMerge(duration, delay)) {
4394
4629
  previousWebAnimationPlayers.forEach(player => {
4395
- let styles = player.currentSnapshot;
4396
- Object.keys(styles).forEach(prop => previousStyles[prop] = styles[prop]);
4630
+ player.currentSnapshot.forEach((val, prop) => previousStyles.set(prop, val));
4397
4631
  });
4398
4632
  }
4399
- keyframes = keyframes.map(styles => copyStyles(styles, false));
4400
- keyframes = balancePreviousStylesIntoKeyframes(element, keyframes, previousStyles);
4401
- const specialStyles = packageNonAnimatableStyles(element, keyframes);
4402
- return new WebAnimationsPlayer(element, keyframes, playerOptions, specialStyles);
4633
+ let _keyframes = normalizeKeyframes(keyframes).map(styles => copyStyles(styles));
4634
+ _keyframes = balancePreviousStylesIntoKeyframes(element, _keyframes, previousStyles);
4635
+ const specialStyles = packageNonAnimatableStyles(element, _keyframes);
4636
+ return new WebAnimationsPlayer(element, _keyframes, playerOptions, specialStyles);
4403
4637
  }
4404
4638
  }
4405
4639
 
@@ -4439,5 +4673,5 @@ class WebAnimationsDriver {
4439
4673
  * Generated bundle index. Do not edit.
4440
4674
  */
4441
4675
 
4442
- 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 };
4676
+ 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 };
4443
4677
  //# sourceMappingURL=browser.mjs.map