@angular/animations 14.0.0-next.0 → 14.0.0-next.11

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 (50) hide show
  1. package/animations.d.ts +16 -3
  2. package/browser/browser.d.ts +29 -94
  3. package/browser/testing/testing.d.ts +10 -15
  4. package/esm2020/browser/src/dsl/animation.mjs +10 -6
  5. package/esm2020/browser/src/dsl/animation_ast.mjs +1 -1
  6. package/esm2020/browser/src/dsl/animation_ast_builder.mjs +80 -70
  7. package/esm2020/browser/src/dsl/animation_dsl_visitor.mjs +1 -1
  8. package/esm2020/browser/src/dsl/animation_timeline_builder.mjs +79 -88
  9. package/esm2020/browser/src/dsl/animation_timeline_instruction.mjs +1 -1
  10. package/esm2020/browser/src/dsl/animation_transition_expr.mjs +4 -3
  11. package/esm2020/browser/src/dsl/animation_transition_factory.mjs +29 -18
  12. package/esm2020/browser/src/dsl/animation_transition_instruction.mjs +8 -1
  13. package/esm2020/browser/src/dsl/animation_trigger.mjs +9 -9
  14. package/esm2020/browser/src/dsl/style_normalization/animation_style_normalizer.mjs +1 -1
  15. package/esm2020/browser/src/dsl/style_normalization/web_animations_style_normalizer.mjs +35 -10
  16. package/esm2020/browser/src/error_helpers.mjs +135 -0
  17. package/esm2020/browser/src/errors.mjs +9 -0
  18. package/esm2020/browser/src/private_export.mjs +4 -6
  19. package/esm2020/browser/src/render/animation_driver.mjs +8 -5
  20. package/esm2020/browser/src/render/animation_engine_next.mjs +9 -3
  21. package/esm2020/browser/src/render/shared.mjs +39 -33
  22. package/esm2020/browser/src/render/special_cased_styles.mjs +7 -16
  23. package/esm2020/browser/src/render/timeline_animation_engine.mjs +26 -20
  24. package/esm2020/browser/src/render/transition_animation_engine.mjs +82 -88
  25. package/esm2020/browser/src/render/web_animations/animatable_props_set.mjs +214 -0
  26. package/esm2020/browser/src/render/web_animations/web_animations_driver.mjs +21 -29
  27. package/esm2020/browser/src/render/web_animations/web_animations_player.mjs +16 -9
  28. package/esm2020/browser/src/util.mjs +48 -37
  29. package/esm2020/browser/src/warning_helpers.mjs +38 -0
  30. package/esm2020/browser/testing/src/mock_animation_driver.mjs +23 -14
  31. package/esm2020/src/animation_metadata.mjs +10 -2
  32. package/esm2020/src/animations.mjs +1 -1
  33. package/esm2020/src/version.mjs +1 -1
  34. package/fesm2015/animations.mjs +10 -2
  35. package/fesm2015/animations.mjs.map +1 -1
  36. package/fesm2015/browser/testing.mjs +859 -15
  37. package/fesm2015/browser/testing.mjs.map +1 -1
  38. package/fesm2015/browser.mjs +863 -858
  39. package/fesm2015/browser.mjs.map +1 -1
  40. package/fesm2020/animations.mjs +10 -2
  41. package/fesm2020/animations.mjs.map +1 -1
  42. package/fesm2020/browser/testing.mjs +859 -15
  43. package/fesm2020/browser/testing.mjs.map +1 -1
  44. package/fesm2020/browser.mjs +861 -857
  45. package/fesm2020/browser.mjs.map +1 -1
  46. package/package.json +3 -3
  47. package/esm2020/browser/src/render/css_keyframes/css_keyframes_driver.mjs +0 -121
  48. package/esm2020/browser/src/render/css_keyframes/css_keyframes_player.mjs +0 -133
  49. package/esm2020/browser/src/render/css_keyframes/direct_style_player.mjs +0 -51
  50. package/esm2020/browser/src/render/css_keyframes/element_animation_style_handler.mjs +0 -137
@@ -1,12 +1,360 @@
1
1
  /**
2
- * @license Angular v14.0.0-next.0
2
+ * @license Angular v14.0.0-next.11
3
3
  * (c) 2010-2022 Google LLC. https://angular.io/
4
4
  * License: MIT
5
5
  */
6
6
 
7
7
  import { ɵAnimationGroupPlayer, NoopAnimationPlayer, AUTO_STYLE, ɵPRE_STYLE, sequence, style } from '@angular/animations';
8
8
  import * as i0 from '@angular/core';
9
- import { Injectable } from '@angular/core';
9
+ import { ɵRuntimeError, Injectable } from '@angular/core';
10
+
11
+ /**
12
+ * @license
13
+ * Copyright Google LLC All Rights Reserved.
14
+ *
15
+ * Use of this source code is governed by an MIT-style license that can be
16
+ * found in the LICENSE file at https://angular.io/license
17
+ */
18
+ const NG_DEV_MODE$1 = typeof ngDevMode === 'undefined' || !!ngDevMode;
19
+ const LINE_START = '\n - ';
20
+ function invalidTimingValue(exp) {
21
+ return new ɵRuntimeError(3000 /* INVALID_TIMING_VALUE */, NG_DEV_MODE$1 && `The provided timing value "${exp}" is invalid.`);
22
+ }
23
+ function negativeStepValue() {
24
+ return new ɵRuntimeError(3100 /* NEGATIVE_STEP_VALUE */, NG_DEV_MODE$1 && 'Duration values below 0 are not allowed for this animation step.');
25
+ }
26
+ function negativeDelayValue() {
27
+ return new ɵRuntimeError(3101 /* NEGATIVE_DELAY_VALUE */, NG_DEV_MODE$1 && 'Delay values below 0 are not allowed for this animation step.');
28
+ }
29
+ function invalidStyleParams(varName) {
30
+ return new ɵRuntimeError(3001 /* INVALID_STYLE_PARAMS */, NG_DEV_MODE$1 &&
31
+ `Unable to resolve the local animation param ${varName} in the given list of values`);
32
+ }
33
+ function invalidParamValue(varName) {
34
+ return new ɵRuntimeError(3003 /* INVALID_PARAM_VALUE */, NG_DEV_MODE$1 && `Please provide a value for the animation param ${varName}`);
35
+ }
36
+ function invalidNodeType(nodeType) {
37
+ return new ɵRuntimeError(3004 /* INVALID_NODE_TYPE */, NG_DEV_MODE$1 && `Unable to resolve animation metadata node #${nodeType}`);
38
+ }
39
+ function invalidCssUnitValue(userProvidedProperty, value) {
40
+ return new ɵRuntimeError(3005 /* INVALID_CSS_UNIT_VALUE */, NG_DEV_MODE$1 && `Please provide a CSS unit value for ${userProvidedProperty}:${value}`);
41
+ }
42
+ function invalidTrigger() {
43
+ return new ɵRuntimeError(3006 /* INVALID_TRIGGER */, NG_DEV_MODE$1 &&
44
+ 'animation triggers cannot be prefixed with an `@` sign (e.g. trigger(\'@foo\', [...]))');
45
+ }
46
+ function invalidDefinition() {
47
+ return new ɵRuntimeError(3007 /* INVALID_DEFINITION */, NG_DEV_MODE$1 && 'only state() and transition() definitions can sit inside of a trigger()');
48
+ }
49
+ function invalidState(metadataName, missingSubs) {
50
+ return new ɵRuntimeError(3008 /* INVALID_STATE */, NG_DEV_MODE$1 &&
51
+ `state("${metadataName}", ...) must define default values for all the following style substitutions: ${missingSubs.join(', ')}`);
52
+ }
53
+ function invalidStyleValue(value) {
54
+ return new ɵRuntimeError(3002 /* INVALID_STYLE_VALUE */, NG_DEV_MODE$1 && `The provided style string value ${value} is not allowed.`);
55
+ }
56
+ function invalidProperty(prop) {
57
+ return new ɵRuntimeError(3009 /* INVALID_PROPERTY */, NG_DEV_MODE$1 &&
58
+ `The provided animation property "${prop}" is not a supported CSS property for animations`);
59
+ }
60
+ function invalidParallelAnimation(prop, firstStart, firstEnd, secondStart, secondEnd) {
61
+ return new ɵRuntimeError(3010 /* INVALID_PARALLEL_ANIMATION */, NG_DEV_MODE$1 &&
62
+ `The CSS property "${prop}" that exists between the times of "${firstStart}ms" and "${firstEnd}ms" is also being animated in a parallel animation between the times of "${secondStart}ms" and "${secondEnd}ms"`);
63
+ }
64
+ function invalidKeyframes() {
65
+ return new ɵRuntimeError(3011 /* INVALID_KEYFRAMES */, NG_DEV_MODE$1 && `keyframes() must be placed inside of a call to animate()`);
66
+ }
67
+ function invalidOffset() {
68
+ return new ɵRuntimeError(3012 /* INVALID_OFFSET */, NG_DEV_MODE$1 && `Please ensure that all keyframe offsets are between 0 and 1`);
69
+ }
70
+ function keyframeOffsetsOutOfOrder() {
71
+ return new ɵRuntimeError(3200 /* KEYFRAME_OFFSETS_OUT_OF_ORDER */, NG_DEV_MODE$1 && `Please ensure that all keyframe offsets are in order`);
72
+ }
73
+ function keyframesMissingOffsets() {
74
+ return new ɵRuntimeError(3202 /* KEYFRAMES_MISSING_OFFSETS */, NG_DEV_MODE$1 && `Not all style() steps within the declared keyframes() contain offsets`);
75
+ }
76
+ function invalidStagger() {
77
+ return new ɵRuntimeError(3013 /* INVALID_STAGGER */, NG_DEV_MODE$1 && `stagger() can only be used inside of query()`);
78
+ }
79
+ function invalidQuery(selector) {
80
+ return new ɵRuntimeError(3014 /* INVALID_QUERY */, NG_DEV_MODE$1 &&
81
+ `\`query("${selector}")\` returned zero elements. (Use \`query("${selector}", { optional: true })\` if you wish to allow this.)`);
82
+ }
83
+ function invalidExpression(expr) {
84
+ return new ɵRuntimeError(3015 /* INVALID_EXPRESSION */, NG_DEV_MODE$1 && `The provided transition expression "${expr}" is not supported`);
85
+ }
86
+ function invalidTransitionAlias(alias) {
87
+ return new ɵRuntimeError(3016 /* INVALID_TRANSITION_ALIAS */, NG_DEV_MODE$1 && `The transition alias value "${alias}" is not supported`);
88
+ }
89
+ function validationFailed(errors) {
90
+ return new ɵRuntimeError(3500 /* VALIDATION_FAILED */, NG_DEV_MODE$1 && `animation validation failed:\n${errors.map(err => err.message).join('\n')}`);
91
+ }
92
+ function buildingFailed(errors) {
93
+ return new ɵRuntimeError(3501 /* BUILDING_FAILED */, NG_DEV_MODE$1 && `animation building failed:\n${errors.map(err => err.message).join('\n')}`);
94
+ }
95
+ function triggerBuildFailed(name, errors) {
96
+ return new ɵRuntimeError(3404 /* TRIGGER_BUILD_FAILED */, NG_DEV_MODE$1 &&
97
+ `The animation trigger "${name}" has failed to build due to the following errors:\n - ${errors.map(err => err.message).join('\n - ')}`);
98
+ }
99
+ function animationFailed(errors) {
100
+ return new ɵRuntimeError(3502 /* ANIMATION_FAILED */, NG_DEV_MODE$1 &&
101
+ `Unable to animate due to the following errors:${LINE_START}${errors.map(err => err.message).join(LINE_START)}`);
102
+ }
103
+ function registerFailed(errors) {
104
+ return new ɵRuntimeError(3503 /* REGISTRATION_FAILED */, NG_DEV_MODE$1 &&
105
+ `Unable to build the animation due to the following errors: ${errors.map(err => err.message).join('\n')}`);
106
+ }
107
+ function missingOrDestroyedAnimation() {
108
+ return new ɵRuntimeError(3300 /* MISSING_OR_DESTROYED_ANIMATION */, NG_DEV_MODE$1 && 'The requested animation doesn\'t exist or has already been destroyed');
109
+ }
110
+ function createAnimationFailed(errors) {
111
+ return new ɵRuntimeError(3504 /* CREATE_ANIMATION_FAILED */, NG_DEV_MODE$1 &&
112
+ `Unable to create the animation due to the following errors:${errors.map(err => err.message).join('\n')}`);
113
+ }
114
+ function missingPlayer(id) {
115
+ return new ɵRuntimeError(3301 /* MISSING_PLAYER */, NG_DEV_MODE$1 && `Unable to find the timeline player referenced by ${id}`);
116
+ }
117
+ function missingTrigger(phase, name) {
118
+ return new ɵRuntimeError(3302 /* MISSING_TRIGGER */, NG_DEV_MODE$1 &&
119
+ `Unable to listen on the animation trigger event "${phase}" because the animation trigger "${name}" doesn\'t exist!`);
120
+ }
121
+ function missingEvent(name) {
122
+ return new ɵRuntimeError(3303 /* MISSING_EVENT */, NG_DEV_MODE$1 &&
123
+ `Unable to listen on the animation trigger "${name}" because the provided event is undefined!`);
124
+ }
125
+ function unsupportedTriggerEvent(phase, name) {
126
+ return new ɵRuntimeError(3400 /* UNSUPPORTED_TRIGGER_EVENT */, NG_DEV_MODE$1 &&
127
+ `The provided animation trigger event "${phase}" for the animation trigger "${name}" is not supported!`);
128
+ }
129
+ function unregisteredTrigger(name) {
130
+ return new ɵRuntimeError(3401 /* UNREGISTERED_TRIGGER */, NG_DEV_MODE$1 && `The provided animation trigger "${name}" has not been registered!`);
131
+ }
132
+ function triggerTransitionsFailed(errors) {
133
+ return new ɵRuntimeError(3402 /* TRIGGER_TRANSITIONS_FAILED */, NG_DEV_MODE$1 &&
134
+ `Unable to process animations due to the following failed trigger transitions\n ${errors.map(err => err.message).join('\n')}`);
135
+ }
136
+ function triggerParsingFailed(name, errors) {
137
+ return new ɵRuntimeError(3403 /* TRIGGER_PARSING_FAILED */, NG_DEV_MODE$1 &&
138
+ `Animation parsing for the ${name} trigger have failed:${LINE_START}${errors.map(err => err.message).join(LINE_START)}`);
139
+ }
140
+ function transitionFailed(name, errors) {
141
+ return new ɵRuntimeError(3505 /* TRANSITION_FAILED */, NG_DEV_MODE$1 &&
142
+ `@${name} has failed due to:\n ${errors.map(err => err.message).join('\n- ')}`);
143
+ }
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
+ ]);
10
358
 
11
359
  /**
12
360
  * @license
@@ -36,26 +384,26 @@ function optimizeGroupPlayer(players) {
36
384
  return new ɵAnimationGroupPlayer(players);
37
385
  }
38
386
  }
39
- function normalizeKeyframes(driver, normalizer, element, keyframes, preStyles = {}, postStyles = {}) {
387
+ function normalizeKeyframes$1(driver, normalizer, element, keyframes, preStyles = new Map(), postStyles = new Map()) {
40
388
  const errors = [];
41
389
  const normalizedKeyframes = [];
42
390
  let previousOffset = -1;
43
391
  let previousKeyframe = null;
44
392
  keyframes.forEach(kf => {
45
- const offset = kf['offset'];
393
+ const offset = kf.get('offset');
46
394
  const isSameOffset = offset == previousOffset;
47
- const normalizedKeyframe = (isSameOffset && previousKeyframe) || {};
48
- Object.keys(kf).forEach(prop => {
395
+ const normalizedKeyframe = (isSameOffset && previousKeyframe) || new Map();
396
+ kf.forEach((val, prop) => {
49
397
  let normalizedProp = prop;
50
- let normalizedValue = kf[prop];
398
+ let normalizedValue = val;
51
399
  if (prop !== 'offset') {
52
400
  normalizedProp = normalizer.normalizePropertyName(normalizedProp, errors);
53
401
  switch (normalizedValue) {
54
402
  case ɵPRE_STYLE:
55
- normalizedValue = preStyles[prop];
403
+ normalizedValue = preStyles.get(prop);
56
404
  break;
57
405
  case AUTO_STYLE:
58
- normalizedValue = postStyles[prop];
406
+ normalizedValue = postStyles.get(prop);
59
407
  break;
60
408
  default:
61
409
  normalizedValue =
@@ -63,7 +411,7 @@ function normalizeKeyframes(driver, normalizer, element, keyframes, preStyles =
63
411
  break;
64
412
  }
65
413
  }
66
- normalizedKeyframe[normalizedProp] = normalizedValue;
414
+ normalizedKeyframe.set(normalizedProp, normalizedValue);
67
415
  });
68
416
  if (!isSameOffset) {
69
417
  normalizedKeyframes.push(normalizedKeyframe);
@@ -72,8 +420,7 @@ function normalizeKeyframes(driver, normalizer, element, keyframes, preStyles =
72
420
  previousOffset = offset;
73
421
  });
74
422
  if (errors.length) {
75
- const LINE_START = '\n - ';
76
- throw new Error(`Unable to animate due to the following errors:${LINE_START}${errors.join(LINE_START)}`);
423
+ throw animationFailed(errors);
77
424
  }
78
425
  return normalizedKeyframes;
79
426
  }
@@ -103,32 +450,31 @@ function copyAnimationEvent(e, phaseName, player) {
103
450
  function makeAnimationEvent(element, triggerName, fromState, toState, phaseName = '', totalTime = 0, disabled) {
104
451
  return { element, triggerName, fromState, toState, phaseName, totalTime, disabled: !!disabled };
105
452
  }
106
- function getOrSetAsInMap(map, key, defaultValue) {
107
- let value;
108
- if (map instanceof Map) {
109
- value = map.get(key);
110
- if (!value) {
111
- map.set(key, value = defaultValue);
112
- }
113
- }
114
- else {
115
- value = map[key];
116
- if (!value) {
117
- value = map[key] = defaultValue;
118
- }
453
+ function getOrSetDefaultValue(map, key, defaultValue) {
454
+ let value = map.get(key);
455
+ if (!value) {
456
+ map.set(key, value = defaultValue);
119
457
  }
120
458
  return value;
121
459
  }
122
460
  function parseTimelineCommand(command) {
123
461
  const separatorPos = command.indexOf(':');
124
462
  const id = command.substring(1, separatorPos);
125
- const action = command.substr(separatorPos + 1);
463
+ const action = command.slice(separatorPos + 1);
126
464
  return [id, action];
127
465
  }
128
466
  let _contains = (elm1, elm2) => false;
129
467
  let _query = (element, selector, multi) => {
130
468
  return [];
131
469
  };
470
+ let _documentElement = null;
471
+ function getParentElement(element) {
472
+ const parent = element.parentNode || element.host; // consider host to support shadow DOM
473
+ if (parent === _documentElement) {
474
+ return null;
475
+ }
476
+ return parent;
477
+ }
132
478
  // Define utility methods for browsers and platform-server(domino) where Element
133
479
  // and utility methods exist.
134
480
  const _isNode = isNode();
@@ -137,12 +483,15 @@ if (_isNode || typeof Element !== 'undefined') {
137
483
  _contains = (elm1, elm2) => elm1.contains(elm2);
138
484
  }
139
485
  else {
486
+ // Read the document element in an IIFE that's been marked pure to avoid a top-level property
487
+ // read that may prevent tree-shaking.
488
+ _documentElement = /* @__PURE__ */ (() => document.documentElement)();
140
489
  _contains = (elm1, elm2) => {
141
- while (elm2 && elm2 !== document.documentElement) {
490
+ while (elm2) {
142
491
  if (elm2 === elm1) {
143
492
  return true;
144
493
  }
145
- elm2 = elm2.parentNode || elm2.host; // consider host to support shadow DOM
494
+ elm2 = getParentElement(elm2);
146
495
  }
147
496
  return false;
148
497
  };
@@ -171,12 +520,15 @@ function validateStyleProperty(prop) {
171
520
  if (_CACHED_BODY.style && !containsVendorPrefix(prop)) {
172
521
  result = prop in _CACHED_BODY.style;
173
522
  if (!result && _IS_WEBKIT) {
174
- const camelProp = 'Webkit' + prop.charAt(0).toUpperCase() + prop.substr(1);
523
+ const camelProp = 'Webkit' + prop.charAt(0).toUpperCase() + prop.slice(1);
175
524
  result = camelProp in _CACHED_BODY.style;
176
525
  }
177
526
  }
178
527
  return result;
179
528
  }
529
+ function validateWebAnimatableStyleProperty(prop) {
530
+ return ANIMATABLE_PROP_SET.has(prop);
531
+ }
180
532
  function getBodyNode() {
181
533
  if (typeof document != 'undefined') {
182
534
  return document.body;
@@ -185,13 +537,13 @@ function getBodyNode() {
185
537
  }
186
538
  const containsElement = _contains;
187
539
  const invokeQuery = _query;
188
- function hypenatePropsObject(object) {
189
- const newObj = {};
190
- Object.keys(object).forEach(prop => {
540
+ function hypenatePropsKeys(original) {
541
+ const newMap = new Map();
542
+ original.forEach((val, prop) => {
191
543
  const newProp = prop.replace(/([a-z])([A-Z])/g, '$1-$2');
192
- newObj[newProp] = object[prop];
544
+ newMap.set(newProp, val);
193
545
  });
194
- return newObj;
546
+ return newMap;
195
547
  }
196
548
 
197
549
  /**
@@ -215,6 +567,9 @@ class NoopAnimationDriver {
215
567
  containsElement(elm1, elm2) {
216
568
  return containsElement(elm1, elm2);
217
569
  }
570
+ getParentElement(element) {
571
+ return getParentElement(element);
572
+ }
218
573
  query(element, selector, multi) {
219
574
  return invokeQuery(element, selector, multi);
220
575
  }
@@ -225,9 +580,9 @@ class NoopAnimationDriver {
225
580
  return new NoopAnimationPlayer(duration, delay);
226
581
  }
227
582
  }
228
- NoopAnimationDriver.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.0", ngImport: i0, type: NoopAnimationDriver, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
229
- NoopAnimationDriver.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.0-next.0", ngImport: i0, type: NoopAnimationDriver });
230
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.0", ngImport: i0, type: NoopAnimationDriver, decorators: [{
583
+ NoopAnimationDriver.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.11", ngImport: i0, type: NoopAnimationDriver, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
584
+ NoopAnimationDriver.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.0-next.11", ngImport: i0, type: NoopAnimationDriver });
585
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.11", ngImport: i0, type: NoopAnimationDriver, decorators: [{
231
586
  type: Injectable
232
587
  }] });
233
588
  /**
@@ -244,7 +599,7 @@ AnimationDriver.NOOP = ( /* @__PURE__ */new NoopAnimationDriver());
244
599
  * Use of this source code is governed by an MIT-style license that can be
245
600
  * found in the LICENSE file at https://angular.io/license
246
601
  */
247
- const ONE_SECOND$1 = 1000;
602
+ const ONE_SECOND = 1000;
248
603
  const SUBSTITUTION_EXPR_START = '{{';
249
604
  const SUBSTITUTION_EXPR_END = '}}';
250
605
  const ENTER_CLASSNAME = 'ng-enter';
@@ -264,7 +619,7 @@ function resolveTimingValue(value) {
264
619
  function _convertTimeValueToMS(value, unit) {
265
620
  switch (unit) {
266
621
  case 's':
267
- return value * ONE_SECOND$1;
622
+ return value * ONE_SECOND;
268
623
  default: // ms or something else
269
624
  return value;
270
625
  }
@@ -282,7 +637,7 @@ function parseTimeExpression(exp, errors, allowNegativeValues) {
282
637
  if (typeof exp === 'string') {
283
638
  const matches = exp.match(regex);
284
639
  if (matches === null) {
285
- errors.push(`The provided timing value "${exp}" is invalid.`);
640
+ errors.push(invalidTimingValue(exp));
286
641
  return { duration: 0, delay: 0, easing: '' };
287
642
  }
288
643
  duration = _convertTimeValueToMS(parseFloat(matches[1]), matches[2]);
@@ -302,15 +657,15 @@ function parseTimeExpression(exp, errors, allowNegativeValues) {
302
657
  let containsErrors = false;
303
658
  let startIndex = errors.length;
304
659
  if (duration < 0) {
305
- errors.push(`Duration values below 0 are not allowed for this animation step.`);
660
+ errors.push(negativeStepValue());
306
661
  containsErrors = true;
307
662
  }
308
663
  if (delay < 0) {
309
- errors.push(`Delay values below 0 are not allowed for this animation step.`);
664
+ errors.push(negativeDelayValue());
310
665
  containsErrors = true;
311
666
  }
312
667
  if (containsErrors) {
313
- errors.splice(startIndex, 0, `The provided timing value "${exp}" is invalid.`);
668
+ errors.splice(startIndex, 0, invalidTimingValue(exp));
314
669
  }
315
670
  }
316
671
  return { duration, delay, easing };
@@ -321,27 +676,41 @@ function copyObj(obj, destination = {}) {
321
676
  });
322
677
  return destination;
323
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
+ }
324
696
  function normalizeStyles(styles) {
325
- const normalizedStyles = {};
697
+ const normalizedStyles = new Map();
326
698
  if (Array.isArray(styles)) {
327
- styles.forEach(data => copyStyles(data, false, normalizedStyles));
699
+ styles.forEach(data => copyStyles(data, normalizedStyles));
328
700
  }
329
701
  else {
330
- copyStyles(styles, false, normalizedStyles);
702
+ copyStyles(styles, normalizedStyles);
331
703
  }
332
704
  return normalizedStyles;
333
705
  }
334
- function copyStyles(styles, readPrototype, destination = {}) {
335
- if (readPrototype) {
336
- // we make use of a for-in loop so that the
337
- // prototypically inherited properties are
338
- // revealed from the backFill map
339
- for (let prop in styles) {
340
- 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);
341
710
  }
342
711
  }
343
- else {
344
- copyObj(styles, destination);
712
+ for (let [prop, val] of styles) {
713
+ destination.set(prop, val);
345
714
  }
346
715
  return destination;
347
716
  }
@@ -377,12 +746,12 @@ function writeStyleAttribute(element) {
377
746
  }
378
747
  function setStyles(element, styles, formerStyles) {
379
748
  if (element['style']) {
380
- Object.keys(styles).forEach(prop => {
749
+ styles.forEach((val, prop) => {
381
750
  const camelProp = dashCaseToCamelCase(prop);
382
- if (formerStyles && !formerStyles.hasOwnProperty(prop)) {
383
- formerStyles[prop] = element.style[camelProp];
751
+ if (formerStyles && !formerStyles.has(prop)) {
752
+ formerStyles.set(prop, element.style[camelProp]);
384
753
  }
385
- element.style[camelProp] = styles[prop];
754
+ element.style[camelProp] = val;
386
755
  });
387
756
  // On the server set the 'style' attribute since it's not automatically reflected.
388
757
  if (isNode()) {
@@ -392,7 +761,7 @@ function setStyles(element, styles, formerStyles) {
392
761
  }
393
762
  function eraseStyles(element, styles) {
394
763
  if (element['style']) {
395
- Object.keys(styles).forEach(prop => {
764
+ styles.forEach((_, prop) => {
396
765
  const camelProp = dashCaseToCamelCase(prop);
397
766
  element.style[camelProp] = '';
398
767
  });
@@ -416,7 +785,7 @@ function validateStyleParams(value, options, errors) {
416
785
  if (matches.length) {
417
786
  matches.forEach(varName => {
418
787
  if (!params.hasOwnProperty(varName)) {
419
- errors.push(`Unable to resolve the local animation param ${varName} in the given list of values`);
788
+ errors.push(invalidStyleParams(varName));
420
789
  }
421
790
  });
422
791
  }
@@ -438,8 +807,8 @@ function interpolateParams(value, params, errors) {
438
807
  const str = original.replace(PARAM_REGEX, (_, varName) => {
439
808
  let localVal = params[varName];
440
809
  // this means that the value was never overridden by the data passed in by the user
441
- if (!params.hasOwnProperty(varName)) {
442
- errors.push(`Please provide a value for the animation param ${varName}`);
810
+ if (localVal == null) {
811
+ errors.push(invalidParamValue(varName));
443
812
  localVal = '';
444
813
  }
445
814
  return localVal.toString();
@@ -467,23 +836,19 @@ function allowPreviousPlayerStylesMerge(duration, delay) {
467
836
  return duration === 0 || delay === 0;
468
837
  }
469
838
  function balancePreviousStylesIntoKeyframes(element, keyframes, previousStyles) {
470
- const previousStyleProps = Object.keys(previousStyles);
471
- if (previousStyleProps.length && keyframes.length) {
839
+ if (previousStyles.size && keyframes.length) {
472
840
  let startingKeyframe = keyframes[0];
473
841
  let missingStyleProps = [];
474
- previousStyleProps.forEach(prop => {
475
- if (!startingKeyframe.hasOwnProperty(prop)) {
842
+ previousStyles.forEach((val, prop) => {
843
+ if (!startingKeyframe.has(prop)) {
476
844
  missingStyleProps.push(prop);
477
845
  }
478
- startingKeyframe[prop] = previousStyles[prop];
846
+ startingKeyframe.set(prop, val);
479
847
  });
480
848
  if (missingStyleProps.length) {
481
- // tslint:disable-next-line
482
- for (var i = 1; i < keyframes.length; i++) {
849
+ for (let i = 1; i < keyframes.length; i++) {
483
850
  let kf = keyframes[i];
484
- missingStyleProps.forEach(function (prop) {
485
- kf[prop] = computeStyle(element, prop);
486
- });
851
+ missingStyleProps.forEach(prop => kf.set(prop, computeStyle(element, prop)));
487
852
  }
488
853
  }
489
854
  }
@@ -518,13 +883,51 @@ function visitDslNode(visitor, node, context) {
518
883
  case 12 /* Stagger */:
519
884
  return visitor.visitStagger(node, context);
520
885
  default:
521
- throw new Error(`Unable to resolve animation metadata node #${node.type}`);
886
+ throw invalidNodeType(node.type);
522
887
  }
523
888
  }
524
889
  function computeStyle(element, prop) {
525
890
  return window.getComputedStyle(element)[prop];
526
891
  }
527
892
 
893
+ /**
894
+ * @license
895
+ * Copyright Google LLC All Rights Reserved.
896
+ *
897
+ * Use of this source code is governed by an MIT-style license that can be
898
+ * found in the LICENSE file at https://angular.io/license
899
+ */
900
+ const NG_DEV_MODE = typeof ngDevMode === 'undefined' || !!ngDevMode;
901
+ function createListOfWarnings(warnings) {
902
+ const LINE_START = '\n - ';
903
+ return `${LINE_START}${warnings.filter(Boolean).map(warning => warning).join(LINE_START)}`;
904
+ }
905
+ function warnValidation(warnings) {
906
+ NG_DEV_MODE && console.warn(`animation validation warnings:${createListOfWarnings(warnings)}`);
907
+ }
908
+ function warnTriggerBuild(name, warnings) {
909
+ NG_DEV_MODE &&
910
+ console.warn(`The animation trigger "${name}" has built with the following warnings:${createListOfWarnings(warnings)}`);
911
+ }
912
+ function warnRegister(warnings) {
913
+ NG_DEV_MODE &&
914
+ console.warn(`Animation built with the following warnings:${createListOfWarnings(warnings)}`);
915
+ }
916
+ function triggerParsingWarnings(name, warnings) {
917
+ NG_DEV_MODE &&
918
+ console.warn(`Animation parsing for the ${name} trigger presents the following warnings:${createListOfWarnings(warnings)}`);
919
+ }
920
+ function pushUnrecognizedPropertiesWarning(warnings, props) {
921
+ if (ngDevMode && props.length) {
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)`);
928
+ }
929
+ }
930
+
528
931
  /**
529
932
  * @license
530
933
  * Copyright Google LLC All Rights Reserved.
@@ -554,7 +957,7 @@ function parseInnerTransitionStr(eventStr, expressions, errors) {
554
957
  }
555
958
  const match = eventStr.match(/^(\*|[-\w]+)\s*(<?[=-]>)\s*(\*|[-\w]+)$/);
556
959
  if (match == null || match.length < 4) {
557
- errors.push(`The provided transition expression "${eventStr}" is not supported`);
960
+ errors.push(invalidExpression(eventStr));
558
961
  return expressions;
559
962
  }
560
963
  const fromState = match[1];
@@ -577,7 +980,7 @@ function parseAnimationAlias(alias, errors) {
577
980
  case ':decrement':
578
981
  return (fromState, toState) => parseFloat(toState) < parseFloat(fromState);
579
982
  default:
580
- errors.push(`The transition alias value "${alias}" is not supported`);
983
+ errors.push(invalidTransitionAlias(alias));
581
984
  return '* => *';
582
985
  }
583
986
  }
@@ -648,23 +1051,31 @@ const SELF_TOKEN_REGEX = new RegExp(`\s*${SELF_TOKEN}\s*,?`, 'g');
648
1051
  *
649
1052
  * Otherwise an error will be thrown.
650
1053
  */
651
- function buildAnimationAst(driver, metadata, errors) {
652
- return new AnimationAstBuilderVisitor(driver).build(metadata, errors);
1054
+ function buildAnimationAst(driver, metadata, errors, warnings) {
1055
+ return new AnimationAstBuilderVisitor(driver).build(metadata, errors, warnings);
653
1056
  }
654
1057
  const ROOT_SELECTOR = '';
655
1058
  class AnimationAstBuilderVisitor {
656
1059
  constructor(_driver) {
657
1060
  this._driver = _driver;
658
1061
  }
659
- build(metadata, errors) {
1062
+ build(metadata, errors, warnings) {
660
1063
  const context = new AnimationAstBuilderContext(errors);
661
1064
  this._resetContextStyleTimingState(context);
662
- return visitDslNode(this, normalizeAnimationEntry(metadata), context);
1065
+ const ast = visitDslNode(this, normalizeAnimationEntry(metadata), context);
1066
+ if (context.unsupportedCSSPropertiesFound.size) {
1067
+ pushUnrecognizedPropertiesWarning(warnings, [...context.unsupportedCSSPropertiesFound.keys()]);
1068
+ }
1069
+ if ((typeof ngDevMode === 'undefined' || ngDevMode) &&
1070
+ context.nonAnimatableCSSPropertiesFound.size) {
1071
+ pushNonAnimatablePropertiesWarning(warnings, [...context.nonAnimatableCSSPropertiesFound.keys()]);
1072
+ }
1073
+ return ast;
663
1074
  }
664
1075
  _resetContextStyleTimingState(context) {
665
1076
  context.currentQuerySelector = ROOT_SELECTOR;
666
- context.collectedStyles = {};
667
- context.collectedStyles[ROOT_SELECTOR] = {};
1077
+ context.collectedStyles = new Map();
1078
+ context.collectedStyles.set(ROOT_SELECTOR, new Map());
668
1079
  context.currentTime = 0;
669
1080
  }
670
1081
  visitTrigger(metadata, context) {
@@ -673,7 +1084,7 @@ class AnimationAstBuilderVisitor {
673
1084
  const states = [];
674
1085
  const transitions = [];
675
1086
  if (metadata.name.charAt(0) == '@') {
676
- context.errors.push('animation triggers cannot be prefixed with an `@` sign (e.g. trigger(\'@foo\', [...]))');
1087
+ context.errors.push(invalidTrigger());
677
1088
  }
678
1089
  metadata.definitions.forEach(def => {
679
1090
  this._resetContextStyleTimingState(context);
@@ -693,7 +1104,7 @@ class AnimationAstBuilderVisitor {
693
1104
  transitions.push(transition);
694
1105
  }
695
1106
  else {
696
- context.errors.push('only state() and transition() definitions can sit inside of a trigger()');
1107
+ context.errors.push(invalidDefinition());
697
1108
  }
698
1109
  });
699
1110
  return {
@@ -712,11 +1123,10 @@ class AnimationAstBuilderVisitor {
712
1123
  if (styleAst.containsDynamicStyles) {
713
1124
  const missingSubs = new Set();
714
1125
  const params = astParams || {};
715
- styleAst.styles.forEach(value => {
716
- if (isObject(value)) {
717
- const stylesObj = value;
718
- Object.keys(stylesObj).forEach(prop => {
719
- extractStyleParams(stylesObj[prop]).forEach(sub => {
1126
+ styleAst.styles.forEach(style => {
1127
+ if (style instanceof Map) {
1128
+ style.forEach(value => {
1129
+ extractStyleParams(value).forEach(sub => {
720
1130
  if (!params.hasOwnProperty(sub)) {
721
1131
  missingSubs.add(sub);
722
1132
  }
@@ -726,8 +1136,7 @@ class AnimationAstBuilderVisitor {
726
1136
  });
727
1137
  if (missingSubs.size) {
728
1138
  const missingSubsArr = iteratorToArray(missingSubs.values());
729
- context.errors.push(`state("${metadata
730
- .name}", ...) must define default values for all the following style substitutions: ${missingSubsArr.join(', ')}`);
1139
+ context.errors.push(invalidState(metadata.name, missingSubsArr));
731
1140
  }
732
1141
  }
733
1142
  return {
@@ -813,37 +1222,30 @@ class AnimationAstBuilderVisitor {
813
1222
  }
814
1223
  _makeStyleAst(metadata, context) {
815
1224
  const styles = [];
816
- if (Array.isArray(metadata.styles)) {
817
- metadata.styles.forEach(styleTuple => {
818
- if (typeof styleTuple == 'string') {
819
- if (styleTuple == AUTO_STYLE) {
820
- styles.push(styleTuple);
821
- }
822
- else {
823
- context.errors.push(`The provided style string value ${styleTuple} is not allowed.`);
824
- }
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);
825
1230
  }
826
1231
  else {
827
- styles.push(styleTuple);
1232
+ context.errors.push(invalidStyleValue(styleTuple));
828
1233
  }
829
- });
830
- }
831
- else {
832
- styles.push(metadata.styles);
1234
+ }
1235
+ else {
1236
+ styles.push(convertToMap(styleTuple));
1237
+ }
833
1238
  }
834
1239
  let containsDynamicStyles = false;
835
1240
  let collectedEasing = null;
836
1241
  styles.forEach(styleData => {
837
- if (isObject(styleData)) {
838
- const styleMap = styleData;
839
- const easing = styleMap['easing'];
840
- if (easing) {
841
- collectedEasing = easing;
842
- delete styleMap['easing'];
1242
+ if (styleData instanceof Map) {
1243
+ if (styleData.has('easing')) {
1244
+ collectedEasing = styleData.get('easing');
1245
+ styleData.delete('easing');
843
1246
  }
844
1247
  if (!containsDynamicStyles) {
845
- for (let prop in styleMap) {
846
- const value = styleMap[prop];
1248
+ for (let value of styleData.values()) {
847
1249
  if (value.toString().indexOf(SUBSTITUTION_EXPR_START) >= 0) {
848
1250
  containsDynamicStyles = true;
849
1251
  break;
@@ -869,21 +1271,32 @@ class AnimationAstBuilderVisitor {
869
1271
  startTime -= timings.duration + timings.delay;
870
1272
  }
871
1273
  ast.styles.forEach(tuple => {
872
- if (typeof tuple == 'string')
1274
+ if (typeof tuple === 'string')
873
1275
  return;
874
- Object.keys(tuple).forEach(prop => {
1276
+ tuple.forEach((value, prop) => {
875
1277
  if (!this._driver.validateStyleProperty(prop)) {
876
- context.errors.push(`The provided animation property "${prop}" is not a supported CSS property for animations`);
1278
+ tuple.delete(prop);
1279
+ context.unsupportedCSSPropertiesFound.add(prop);
877
1280
  return;
878
1281
  }
879
- const collectedStyles = context.collectedStyles[context.currentQuerySelector];
880
- 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);
881
1295
  let updateCollectedStyle = true;
882
1296
  if (collectedEntry) {
883
1297
  if (startTime != endTime && startTime >= collectedEntry.startTime &&
884
1298
  endTime <= collectedEntry.endTime) {
885
- context.errors.push(`The CSS property "${prop}" that exists between the times of "${collectedEntry.startTime}ms" and "${collectedEntry
886
- .endTime}ms" is also being animated in a parallel animation between the times of "${startTime}ms" and "${endTime}ms"`);
1299
+ context.errors.push(invalidParallelAnimation(prop, collectedEntry.startTime, collectedEntry.endTime, startTime, endTime));
887
1300
  updateCollectedStyle = false;
888
1301
  }
889
1302
  // we always choose the smaller start time value since we
@@ -892,10 +1305,10 @@ class AnimationAstBuilderVisitor {
892
1305
  startTime = collectedEntry.startTime;
893
1306
  }
894
1307
  if (updateCollectedStyle) {
895
- collectedStyles[prop] = { startTime, endTime };
1308
+ collectedStyles.set(prop, { startTime, endTime });
896
1309
  }
897
1310
  if (context.options) {
898
- validateStyleParams(tuple[prop], context.options, context.errors);
1311
+ validateStyleParams(value, context.options, context.errors);
899
1312
  }
900
1313
  });
901
1314
  });
@@ -903,7 +1316,7 @@ class AnimationAstBuilderVisitor {
903
1316
  visitKeyframes(metadata, context) {
904
1317
  const ast = { type: 5 /* Keyframes */, styles: [], options: null };
905
1318
  if (!context.currentAnimateTimings) {
906
- context.errors.push(`keyframes() must be placed inside of a call to animate()`);
1319
+ context.errors.push(invalidKeyframes());
907
1320
  return ast;
908
1321
  }
909
1322
  const MAX_KEYFRAME_OFFSET = 1;
@@ -927,15 +1340,15 @@ class AnimationAstBuilderVisitor {
927
1340
  return style;
928
1341
  });
929
1342
  if (keyframesOutOfRange) {
930
- context.errors.push(`Please ensure that all keyframe offsets are between 0 and 1`);
1343
+ context.errors.push(invalidOffset());
931
1344
  }
932
1345
  if (offsetsOutOfOrder) {
933
- context.errors.push(`Please ensure that all keyframe offsets are in order`);
1346
+ context.errors.push(keyframeOffsetsOutOfOrder());
934
1347
  }
935
1348
  const length = metadata.steps.length;
936
1349
  let generatedOffset = 0;
937
1350
  if (totalKeyframesWithOffsets > 0 && totalKeyframesWithOffsets < length) {
938
- context.errors.push(`Not all style() steps within the declared keyframes() contain offsets`);
1351
+ context.errors.push(keyframesMissingOffsets());
939
1352
  }
940
1353
  else if (totalKeyframesWithOffsets == 0) {
941
1354
  generatedOffset = MAX_KEYFRAME_OFFSET / (length - 1);
@@ -984,7 +1397,7 @@ class AnimationAstBuilderVisitor {
984
1397
  const [selector, includeSelf] = normalizeSelector(metadata.selector);
985
1398
  context.currentQuerySelector =
986
1399
  parentSelector.length ? (parentSelector + ' ' + selector) : selector;
987
- getOrSetAsInMap(context.collectedStyles, context.currentQuerySelector, {});
1400
+ getOrSetDefaultValue(context.collectedStyles, context.currentQuerySelector, new Map());
988
1401
  const animation = visitDslNode(this, normalizeAnimationEntry(metadata.animation), context);
989
1402
  context.currentQuery = null;
990
1403
  context.currentQuerySelector = parentSelector;
@@ -1001,7 +1414,7 @@ class AnimationAstBuilderVisitor {
1001
1414
  }
1002
1415
  visitStagger(metadata, context) {
1003
1416
  if (!context.currentQuery) {
1004
- context.errors.push(`stagger() can only be used inside of query()`);
1417
+ context.errors.push(invalidStagger());
1005
1418
  }
1006
1419
  const timings = metadata.timings === 'full' ?
1007
1420
  { duration: 0, delay: 0, easing: 'full' } :
@@ -1022,7 +1435,7 @@ function normalizeSelector(selector) {
1022
1435
  // Note: the :enter and :leave aren't normalized here since those
1023
1436
  // selectors are filled in at runtime during timeline building
1024
1437
  selector = selector.replace(/@\*/g, NG_TRIGGER_SELECTOR)
1025
- .replace(/@\w+/g, match => NG_TRIGGER_SELECTOR + '-' + match.substr(1))
1438
+ .replace(/@\w+/g, match => NG_TRIGGER_SELECTOR + '-' + match.slice(1))
1026
1439
  .replace(/:animating/g, NG_ANIMATING_SELECTOR);
1027
1440
  return [selector, hasAmpersand];
1028
1441
  }
@@ -1039,8 +1452,10 @@ class AnimationAstBuilderContext {
1039
1452
  this.currentQuerySelector = null;
1040
1453
  this.currentAnimateTimings = null;
1041
1454
  this.currentTime = 0;
1042
- this.collectedStyles = {};
1455
+ this.collectedStyles = new Map();
1043
1456
  this.options = null;
1457
+ this.unsupportedCSSPropertiesFound = new Set();
1458
+ this.nonAnimatableCSSPropertiesFound = new Set();
1044
1459
  }
1045
1460
  }
1046
1461
  function consumeOffset(styles) {
@@ -1049,29 +1464,25 @@ function consumeOffset(styles) {
1049
1464
  let offset = null;
1050
1465
  if (Array.isArray(styles)) {
1051
1466
  styles.forEach(styleTuple => {
1052
- if (isObject(styleTuple) && styleTuple.hasOwnProperty('offset')) {
1467
+ if (styleTuple instanceof Map && styleTuple.has('offset')) {
1053
1468
  const obj = styleTuple;
1054
- offset = parseFloat(obj['offset']);
1055
- delete obj['offset'];
1469
+ offset = parseFloat(obj.get('offset'));
1470
+ obj.delete('offset');
1056
1471
  }
1057
1472
  });
1058
1473
  }
1059
- else if (isObject(styles) && styles.hasOwnProperty('offset')) {
1474
+ else if (styles instanceof Map && styles.has('offset')) {
1060
1475
  const obj = styles;
1061
- offset = parseFloat(obj['offset']);
1062
- delete obj['offset'];
1476
+ offset = parseFloat(obj.get('offset'));
1477
+ obj.delete('offset');
1063
1478
  }
1064
1479
  return offset;
1065
1480
  }
1066
- function isObject(value) {
1067
- return !Array.isArray(value) && typeof value == 'object';
1068
- }
1069
1481
  function constructTimingAst(value, errors) {
1070
- let timings = null;
1071
1482
  if (value.hasOwnProperty('duration')) {
1072
- timings = value;
1483
+ return value;
1073
1484
  }
1074
- else if (typeof value == 'number') {
1485
+ if (typeof value == 'number') {
1075
1486
  const duration = resolveTiming(value, errors).duration;
1076
1487
  return makeTimingAst(duration, 0, '');
1077
1488
  }
@@ -1083,7 +1494,7 @@ function constructTimingAst(value, errors) {
1083
1494
  ast.strValue = strValue;
1084
1495
  return ast;
1085
1496
  }
1086
- timings = timings || resolveTiming(strValue, errors);
1497
+ const timings = resolveTiming(strValue, errors);
1087
1498
  return makeTimingAst(timings.duration, timings.delay, timings.easing);
1088
1499
  }
1089
1500
  function normalizeAnimationOptions(options) {
@@ -1173,7 +1584,7 @@ const LEAVE_TOKEN_REGEX = new RegExp(LEAVE_TOKEN, 'g');
1173
1584
  * ```
1174
1585
  *
1175
1586
  * For this operation to cover the combination of animation verbs (style, animate, group, etc...) a
1176
- * combination of prototypical inheritance, AST traversal and merge-sort-like algorithms are used.
1587
+ * combination of AST traversal and merge-sort-like algorithms are used.
1177
1588
  *
1178
1589
  * [AST Traversal]
1179
1590
  * Each of the animation verbs, when executed, will return an string-map object representing what
@@ -1219,23 +1630,18 @@ const LEAVE_TOKEN_REGEX = new RegExp(LEAVE_TOKEN, 'g');
1219
1630
  * from all previous animation steps. Therefore when a keyframe is created it would also be missing
1220
1631
  * from all previous keyframes up until where it is first used. For the timeline keyframe generation
1221
1632
  * to properly fill in the style it will place the previous value (the value from the parent
1222
- * timeline) or a default value of `*` into the backFill object. Given that each of the keyframe
1223
- * styles is an object that prototypically inherits from the backFill object, this means that if a
1224
- * value is added into the backFill then it will automatically propagate any missing values to all
1225
- * keyframes. Therefore the missing `height` value will be properly filled into the already
1226
- * processed keyframes.
1633
+ * timeline) or a default value of `*` into the backFill map. The `copyStyles` method in util.ts
1634
+ * handles propagating that backfill map to the styles object.
1227
1635
  *
1228
1636
  * When a sub-timeline is created it will have its own backFill property. This is done so that
1229
1637
  * styles present within the sub-timeline do not accidentally seep into the previous/future timeline
1230
1638
  * keyframes
1231
1639
  *
1232
- * (For prototypically-inherited contents to be detected a `for(i in obj)` loop must be used.)
1233
- *
1234
1640
  * [Validation]
1235
1641
  * The code in this file is not responsible for validation. That functionality happens with within
1236
1642
  * the `AnimationValidatorVisitor` code.
1237
1643
  */
1238
- function buildAnimationTimelines(driver, rootElement, ast, enterClassName, leaveClassName, startingStyles = {}, finalStyles = {}, options, subInstructions, errors = []) {
1644
+ function buildAnimationTimelines(driver, rootElement, ast, enterClassName, leaveClassName, startingStyles = new Map(), finalStyles = new Map(), options, subInstructions, errors = []) {
1239
1645
  return new AnimationTimelineBuilderVisitor().buildKeyframes(driver, rootElement, ast, enterClassName, leaveClassName, startingStyles, finalStyles, options, subInstructions, errors);
1240
1646
  }
1241
1647
  class AnimationTimelineBuilderVisitor {
@@ -1243,15 +1649,17 @@ class AnimationTimelineBuilderVisitor {
1243
1649
  subInstructions = subInstructions || new ElementInstructionMap();
1244
1650
  const context = new AnimationTimelineContext(driver, rootElement, subInstructions, enterClassName, leaveClassName, errors, []);
1245
1651
  context.options = options;
1652
+ const delay = options.delay ? resolveTimingValue(options.delay) : 0;
1653
+ context.currentTimeline.delayNextStep(delay);
1246
1654
  context.currentTimeline.setStyles([startingStyles], null, context.errors, options);
1247
1655
  visitDslNode(this, ast, context);
1248
1656
  // this checks to see if an actual animation happened
1249
1657
  const timelines = context.timelines.filter(timeline => timeline.containsAnimation());
1250
- if (Object.keys(finalStyles).length) {
1251
- // note: we just want to apply the final styles for the rootElement, so we do not
1252
- // just apply the styles to the last timeline but the last timeline which
1253
- // element is the root one (basically `*`-styles are replaced with the actual
1254
- // state style values only for the root element)
1658
+ // note: we just want to apply the final styles for the rootElement, so we do not
1659
+ // just apply the styles to the last timeline but the last timeline which
1660
+ // element is the root one (basically `*`-styles are replaced with the actual
1661
+ // state style values only for the root element)
1662
+ if (timelines.length && finalStyles.size) {
1255
1663
  let lastRootTimeline;
1256
1664
  for (let i = timelines.length - 1; i >= 0; i--) {
1257
1665
  const timeline = timelines[i];
@@ -1264,8 +1672,9 @@ class AnimationTimelineBuilderVisitor {
1264
1672
  lastRootTimeline.setStyles([finalStyles], null, context.errors, options);
1265
1673
  }
1266
1674
  }
1267
- return timelines.length ? timelines.map(timeline => timeline.buildKeyframes()) :
1268
- [createTimelineInstruction(rootElement, [], [], [], 0, 0, '', false)];
1675
+ return timelines.length ?
1676
+ timelines.map(timeline => timeline.buildKeyframes()) :
1677
+ [createTimelineInstruction(rootElement, [], [], [], 0, delay, '', false)];
1269
1678
  }
1270
1679
  visitTrigger(ast, context) {
1271
1680
  // these values are not visited in this AST
@@ -1401,7 +1810,7 @@ class AnimationTimelineBuilderVisitor {
1401
1810
  const timings = context.currentAnimateTimings;
1402
1811
  // this is a special case for when a style() call
1403
1812
  // directly follows an animate() call (but not inside of an animate() call)
1404
- if (!timings && timeline.getCurrentStyleProperties().length) {
1813
+ if (!timings && timeline.hasCurrentStyleProperties()) {
1405
1814
  timeline.forwardFrame();
1406
1815
  }
1407
1816
  const easing = (timings && timings.easing) || ast.easing;
@@ -1442,7 +1851,7 @@ class AnimationTimelineBuilderVisitor {
1442
1851
  const delay = options.delay ? resolveTimingValue(options.delay) : 0;
1443
1852
  if (delay &&
1444
1853
  (context.previousNode.type === 6 /* Style */ ||
1445
- (startTime == 0 && context.currentTimeline.getCurrentStyleProperties().length))) {
1854
+ (startTime == 0 && context.currentTimeline.hasCurrentStyleProperties()))) {
1446
1855
  context.currentTimeline.snapshotCurrentStyles();
1447
1856
  context.previousNode = DEFAULT_NOOP_PREVIOUS_NODE;
1448
1857
  }
@@ -1624,7 +2033,7 @@ class AnimationTimelineContext {
1624
2033
  results.push(...elements);
1625
2034
  }
1626
2035
  if (!optional && results.length == 0) {
1627
- errors.push(`\`query("${originalSelector}")\` returned zero elements. (Use \`query("${originalSelector}", { optional: true })\` if you wish to allow this.)`);
2036
+ errors.push(invalidQuery(originalSelector));
1628
2037
  }
1629
2038
  return results;
1630
2039
  }
@@ -1636,17 +2045,17 @@ class TimelineBuilder {
1636
2045
  this.startTime = startTime;
1637
2046
  this._elementTimelineStylesLookup = _elementTimelineStylesLookup;
1638
2047
  this.duration = 0;
1639
- this._previousKeyframe = {};
1640
- this._currentKeyframe = {};
2048
+ this._previousKeyframe = new Map();
2049
+ this._currentKeyframe = new Map();
1641
2050
  this._keyframes = new Map();
1642
- this._styleSummary = {};
1643
- this._pendingStyles = {};
1644
- this._backFill = {};
2051
+ this._styleSummary = new Map();
2052
+ this._localTimelineStyles = new Map();
2053
+ this._pendingStyles = new Map();
2054
+ this._backFill = new Map();
1645
2055
  this._currentEmptyStepKeyframe = null;
1646
2056
  if (!this._elementTimelineStylesLookup) {
1647
2057
  this._elementTimelineStylesLookup = new Map();
1648
2058
  }
1649
- this._localTimelineStyles = Object.create(this._backFill, {});
1650
2059
  this._globalTimelineStyles = this._elementTimelineStylesLookup.get(element);
1651
2060
  if (!this._globalTimelineStyles) {
1652
2061
  this._globalTimelineStyles = this._localTimelineStyles;
@@ -1659,13 +2068,13 @@ class TimelineBuilder {
1659
2068
  case 0:
1660
2069
  return false;
1661
2070
  case 1:
1662
- return this.getCurrentStyleProperties().length > 0;
2071
+ return this.hasCurrentStyleProperties();
1663
2072
  default:
1664
2073
  return true;
1665
2074
  }
1666
2075
  }
1667
- getCurrentStyleProperties() {
1668
- return Object.keys(this._currentKeyframe);
2076
+ hasCurrentStyleProperties() {
2077
+ return this._currentKeyframe.size > 0;
1669
2078
  }
1670
2079
  get currentTime() {
1671
2080
  return this.startTime + this.duration;
@@ -1675,7 +2084,7 @@ class TimelineBuilder {
1675
2084
  // and that style() step is the very first style() value in the animation
1676
2085
  // then we need to make a copy of the keyframe [0, copy, 1] so that the delay
1677
2086
  // properly applies the style() values to work with the stagger...
1678
- const hasPreStyleStep = this._keyframes.size == 1 && Object.keys(this._pendingStyles).length;
2087
+ const hasPreStyleStep = this._keyframes.size === 1 && this._pendingStyles.size;
1679
2088
  if (this.duration || hasPreStyleStep) {
1680
2089
  this.forwardTime(this.currentTime + delay);
1681
2090
  if (hasPreStyleStep) {
@@ -1696,7 +2105,7 @@ class TimelineBuilder {
1696
2105
  }
1697
2106
  this._currentKeyframe = this._keyframes.get(this.duration);
1698
2107
  if (!this._currentKeyframe) {
1699
- this._currentKeyframe = Object.create(this._backFill, {});
2108
+ this._currentKeyframe = new Map();
1700
2109
  this._keyframes.set(this.duration, this._currentKeyframe);
1701
2110
  }
1702
2111
  }
@@ -1710,16 +2119,16 @@ class TimelineBuilder {
1710
2119
  this._loadKeyframe();
1711
2120
  }
1712
2121
  _updateStyle(prop, value) {
1713
- this._localTimelineStyles[prop] = value;
1714
- this._globalTimelineStyles[prop] = value;
1715
- this._styleSummary[prop] = { time: this.currentTime, value };
2122
+ this._localTimelineStyles.set(prop, value);
2123
+ this._globalTimelineStyles.set(prop, value);
2124
+ this._styleSummary.set(prop, { time: this.currentTime, value });
1716
2125
  }
1717
2126
  allowOnlyTimelineStyles() {
1718
2127
  return this._currentEmptyStepKeyframe !== this._currentKeyframe;
1719
2128
  }
1720
2129
  applyEmptyStep(easing) {
1721
2130
  if (easing) {
1722
- this._previousKeyframe['easing'] = easing;
2131
+ this._previousKeyframe.set('easing', easing);
1723
2132
  }
1724
2133
  // special case for animate(duration):
1725
2134
  // all missing styles are filled with a `*` value then
@@ -1727,51 +2136,45 @@ class TimelineBuilder {
1727
2136
  // keyframe then they will override the overridden styles
1728
2137
  // We use `_globalTimelineStyles` here because there may be
1729
2138
  // styles in previous keyframes that are not present in this timeline
1730
- Object.keys(this._globalTimelineStyles).forEach(prop => {
1731
- this._backFill[prop] = this._globalTimelineStyles[prop] || AUTO_STYLE;
1732
- this._currentKeyframe[prop] = AUTO_STYLE;
1733
- });
2139
+ for (let [prop, value] of this._globalTimelineStyles) {
2140
+ this._backFill.set(prop, value || AUTO_STYLE);
2141
+ this._currentKeyframe.set(prop, AUTO_STYLE);
2142
+ }
1734
2143
  this._currentEmptyStepKeyframe = this._currentKeyframe;
1735
2144
  }
1736
2145
  setStyles(input, easing, errors, options) {
1737
2146
  if (easing) {
1738
- this._previousKeyframe['easing'] = easing;
2147
+ this._previousKeyframe.set('easing', easing);
1739
2148
  }
1740
2149
  const params = (options && options.params) || {};
1741
2150
  const styles = flattenStyles(input, this._globalTimelineStyles);
1742
- Object.keys(styles).forEach(prop => {
1743
- const val = interpolateParams(styles[prop], params, errors);
1744
- this._pendingStyles[prop] = val;
1745
- if (!this._localTimelineStyles.hasOwnProperty(prop)) {
1746
- this._backFill[prop] = this._globalTimelineStyles.hasOwnProperty(prop) ?
1747
- this._globalTimelineStyles[prop] :
1748
- AUTO_STYLE;
2151
+ for (let [prop, value] of styles) {
2152
+ const val = interpolateParams(value, params, errors);
2153
+ this._pendingStyles.set(prop, val);
2154
+ if (!this._localTimelineStyles.has(prop)) {
2155
+ this._backFill.set(prop, this._globalTimelineStyles.get(prop) || AUTO_STYLE);
1749
2156
  }
1750
2157
  this._updateStyle(prop, val);
1751
- });
2158
+ }
1752
2159
  }
1753
2160
  applyStylesToKeyframe() {
1754
- const styles = this._pendingStyles;
1755
- const props = Object.keys(styles);
1756
- if (props.length == 0)
2161
+ if (this._pendingStyles.size == 0)
1757
2162
  return;
1758
- this._pendingStyles = {};
1759
- props.forEach(prop => {
1760
- const val = styles[prop];
1761
- this._currentKeyframe[prop] = val;
2163
+ this._pendingStyles.forEach((val, prop) => {
2164
+ this._currentKeyframe.set(prop, val);
1762
2165
  });
1763
- Object.keys(this._localTimelineStyles).forEach(prop => {
1764
- if (!this._currentKeyframe.hasOwnProperty(prop)) {
1765
- this._currentKeyframe[prop] = this._localTimelineStyles[prop];
2166
+ this._pendingStyles.clear();
2167
+ this._localTimelineStyles.forEach((val, prop) => {
2168
+ if (!this._currentKeyframe.has(prop)) {
2169
+ this._currentKeyframe.set(prop, val);
1766
2170
  }
1767
2171
  });
1768
2172
  }
1769
2173
  snapshotCurrentStyles() {
1770
- Object.keys(this._localTimelineStyles).forEach(prop => {
1771
- const val = this._localTimelineStyles[prop];
1772
- this._pendingStyles[prop] = val;
2174
+ for (let [prop, val] of this._localTimelineStyles) {
2175
+ this._pendingStyles.set(prop, val);
1773
2176
  this._updateStyle(prop, val);
1774
- });
2177
+ }
1775
2178
  }
1776
2179
  getFinalKeyframe() {
1777
2180
  return this._keyframes.get(this.duration);
@@ -1784,9 +2187,8 @@ class TimelineBuilder {
1784
2187
  return properties;
1785
2188
  }
1786
2189
  mergeTimelineCollectedStyles(timeline) {
1787
- Object.keys(timeline._styleSummary).forEach(prop => {
1788
- const details0 = this._styleSummary[prop];
1789
- const details1 = timeline._styleSummary[prop];
2190
+ timeline._styleSummary.forEach((details1, prop) => {
2191
+ const details0 = this._styleSummary.get(prop);
1790
2192
  if (!details0 || details1.time > details0.time) {
1791
2193
  this._updateStyle(prop, details1.value);
1792
2194
  }
@@ -1799,18 +2201,17 @@ class TimelineBuilder {
1799
2201
  const isEmpty = this._keyframes.size === 1 && this.duration === 0;
1800
2202
  let finalKeyframes = [];
1801
2203
  this._keyframes.forEach((keyframe, time) => {
1802
- const finalKeyframe = copyStyles(keyframe, true);
1803
- Object.keys(finalKeyframe).forEach(prop => {
1804
- const value = finalKeyframe[prop];
1805
- if (value == ɵPRE_STYLE) {
2204
+ const finalKeyframe = copyStyles(keyframe, new Map(), this._backFill);
2205
+ finalKeyframe.forEach((value, prop) => {
2206
+ if (value === ɵPRE_STYLE) {
1806
2207
  preStyleProps.add(prop);
1807
2208
  }
1808
- else if (value == AUTO_STYLE) {
2209
+ else if (value === AUTO_STYLE) {
1809
2210
  postStyleProps.add(prop);
1810
2211
  }
1811
2212
  });
1812
2213
  if (!isEmpty) {
1813
- finalKeyframe['offset'] = time / this.duration;
2214
+ finalKeyframe.set('offset', time / this.duration);
1814
2215
  }
1815
2216
  finalKeyframes.push(finalKeyframe);
1816
2217
  });
@@ -1819,9 +2220,9 @@ class TimelineBuilder {
1819
2220
  // special case for a 0-second animation (which is designed just to place styles onscreen)
1820
2221
  if (isEmpty) {
1821
2222
  const kf0 = finalKeyframes[0];
1822
- const kf1 = copyObj(kf0);
1823
- kf0['offset'] = 0;
1824
- kf1['offset'] = 1;
2223
+ const kf1 = new Map(kf0);
2224
+ kf0.set('offset', 0);
2225
+ kf1.set('offset', 1);
1825
2226
  finalKeyframes = [kf0, kf1];
1826
2227
  }
1827
2228
  return createTimelineInstruction(this.element, finalKeyframes, preProps, postProps, this.duration, this.startTime, this.easing, false);
@@ -1847,11 +2248,11 @@ class SubTimelineBuilder extends TimelineBuilder {
1847
2248
  const totalTime = duration + delay;
1848
2249
  const startingGap = delay / totalTime;
1849
2250
  // the original starting keyframe now starts once the delay is done
1850
- const newFirstKeyframe = copyStyles(keyframes[0], false);
1851
- newFirstKeyframe['offset'] = 0;
2251
+ const newFirstKeyframe = copyStyles(keyframes[0]);
2252
+ newFirstKeyframe.set('offset', 0);
1852
2253
  newKeyframes.push(newFirstKeyframe);
1853
- const oldFirstKeyframe = copyStyles(keyframes[0], false);
1854
- oldFirstKeyframe['offset'] = roundOffset(startingGap);
2254
+ const oldFirstKeyframe = copyStyles(keyframes[0]);
2255
+ oldFirstKeyframe.set('offset', roundOffset(startingGap));
1855
2256
  newKeyframes.push(oldFirstKeyframe);
1856
2257
  /*
1857
2258
  When the keyframe is stretched then it means that the delay before the animation
@@ -1870,10 +2271,10 @@ class SubTimelineBuilder extends TimelineBuilder {
1870
2271
  // offsets between 1 ... n -1 are all warped by the keyframe stretch
1871
2272
  const limit = keyframes.length - 1;
1872
2273
  for (let i = 1; i <= limit; i++) {
1873
- let kf = copyStyles(keyframes[i], false);
1874
- const oldOffset = kf['offset'];
2274
+ let kf = copyStyles(keyframes[i]);
2275
+ const oldOffset = kf.get('offset');
1875
2276
  const timeAtKeyframe = delay + oldOffset * duration;
1876
- kf['offset'] = roundOffset(timeAtKeyframe / totalTime);
2277
+ kf.set('offset', roundOffset(timeAtKeyframe / totalTime));
1877
2278
  newKeyframes.push(kf);
1878
2279
  }
1879
2280
  // the new starting keyframe should be added at the start
@@ -1890,17 +2291,17 @@ function roundOffset(offset, decimalPoints = 3) {
1890
2291
  return Math.round(offset * mult) / mult;
1891
2292
  }
1892
2293
  function flattenStyles(input, allStyles) {
1893
- const styles = {};
2294
+ const styles = new Map();
1894
2295
  let allProperties;
1895
2296
  input.forEach(token => {
1896
2297
  if (token === '*') {
1897
- allProperties = allProperties || Object.keys(allStyles);
1898
- allProperties.forEach(prop => {
1899
- styles[prop] = AUTO_STYLE;
1900
- });
2298
+ allProperties = allProperties || allStyles.keys();
2299
+ for (let prop of allProperties) {
2300
+ styles.set(prop, AUTO_STYLE);
2301
+ }
1901
2302
  }
1902
2303
  else {
1903
- copyStyles(token, false, styles);
2304
+ copyStyles(token, styles);
1904
2305
  }
1905
2306
  });
1906
2307
  return styles;
@@ -1910,10 +2311,13 @@ class Animation {
1910
2311
  constructor(_driver, input) {
1911
2312
  this._driver = _driver;
1912
2313
  const errors = [];
1913
- const ast = buildAnimationAst(_driver, input, errors);
2314
+ const warnings = [];
2315
+ const ast = buildAnimationAst(_driver, input, errors, warnings);
1914
2316
  if (errors.length) {
1915
- const errorMessage = `animation validation failed:\n${errors.join('\n')}`;
1916
- throw new Error(errorMessage);
2317
+ throw validationFailed(errors);
2318
+ }
2319
+ if (warnings.length) {
2320
+ warnValidation(warnings);
1917
2321
  }
1918
2322
  this._animationAst = ast;
1919
2323
  }
@@ -1926,8 +2330,7 @@ class Animation {
1926
2330
  subInstructions = subInstructions || new ElementInstructionMap();
1927
2331
  const result = buildAnimationTimelines(this._driver, element, this._animationAst, ENTER_CLASSNAME, LEAVE_CLASSNAME, start, dest, options, subInstructions, errors);
1928
2332
  if (errors.length) {
1929
- const errorMessage = `animation building failed:\n${errors.join('\n')}`;
1930
- throw new Error(errorMessage);
2333
+ throw buildingFailed(errors);
1931
2334
  }
1932
2335
  return result;
1933
2336
  }
@@ -1964,6 +2367,37 @@ class NoopAnimationStyleNormalizer {
1964
2367
  * Use of this source code is governed by an MIT-style license that can be
1965
2368
  * found in the LICENSE file at https://angular.io/license
1966
2369
  */
2370
+ const DIMENSIONAL_PROP_SET = new Set([
2371
+ 'width',
2372
+ 'height',
2373
+ 'minWidth',
2374
+ 'minHeight',
2375
+ 'maxWidth',
2376
+ 'maxHeight',
2377
+ 'left',
2378
+ 'top',
2379
+ 'bottom',
2380
+ 'right',
2381
+ 'fontSize',
2382
+ 'outlineWidth',
2383
+ 'outlineOffset',
2384
+ 'paddingTop',
2385
+ 'paddingLeft',
2386
+ 'paddingBottom',
2387
+ 'paddingRight',
2388
+ 'marginTop',
2389
+ 'marginLeft',
2390
+ 'marginBottom',
2391
+ 'marginRight',
2392
+ 'borderRadius',
2393
+ 'borderWidth',
2394
+ 'borderTopWidth',
2395
+ 'borderLeftWidth',
2396
+ 'borderRightWidth',
2397
+ 'borderBottomWidth',
2398
+ 'textIndent',
2399
+ 'perspective'
2400
+ ]);
1967
2401
  class WebAnimationsStyleNormalizer extends AnimationStyleNormalizer {
1968
2402
  normalizePropertyName(propertyName, errors) {
1969
2403
  return dashCaseToCamelCase(propertyName);
@@ -1971,28 +2405,28 @@ class WebAnimationsStyleNormalizer extends AnimationStyleNormalizer {
1971
2405
  normalizeStyleValue(userProvidedProperty, normalizedProperty, value, errors) {
1972
2406
  let unit = '';
1973
2407
  const strVal = value.toString().trim();
1974
- if (DIMENSIONAL_PROP_MAP[normalizedProperty] && value !== 0 && value !== '0') {
2408
+ if (DIMENSIONAL_PROP_SET.has(normalizedProperty) && value !== 0 && value !== '0') {
1975
2409
  if (typeof value === 'number') {
1976
2410
  unit = 'px';
1977
2411
  }
1978
2412
  else {
1979
2413
  const valAndSuffixMatch = value.match(/^[+-]?[\d\.]+([a-z]*)$/);
1980
2414
  if (valAndSuffixMatch && valAndSuffixMatch[1].length == 0) {
1981
- errors.push(`Please provide a CSS unit value for ${userProvidedProperty}:${value}`);
2415
+ errors.push(invalidCssUnitValue(userProvidedProperty, value));
1982
2416
  }
1983
2417
  }
1984
2418
  }
1985
2419
  return strVal + unit;
1986
2420
  }
1987
2421
  }
1988
- 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'
1989
- .split(',')))();
1990
- function makeBooleanMap(keys) {
1991
- const map = {};
1992
- keys.forEach(key => map[key] = true);
1993
- return map;
1994
- }
1995
2422
 
2423
+ /**
2424
+ * @license
2425
+ * Copyright Google LLC All Rights Reserved.
2426
+ *
2427
+ * Use of this source code is governed by an MIT-style license that can be
2428
+ * found in the LICENSE file at https://angular.io/license
2429
+ */
1996
2430
  function createTransitionInstruction(element, triggerName, fromState, toState, isRemovalTransition, fromStyles, toStyles, timelines, queriedElements, preStyleProps, postStyleProps, totalTime, errors) {
1997
2431
  return {
1998
2432
  type: 0 /* TransitionAnimation */,
@@ -2023,12 +2457,14 @@ class AnimationTransitionFactory {
2023
2457
  return oneOrMoreTransitionsMatch(this.ast.matchers, currentState, nextState, element, params);
2024
2458
  }
2025
2459
  buildStyles(stateName, params, errors) {
2026
- const backupStateStyler = this._stateStyles['*'];
2027
- const stateStyler = this._stateStyles[stateName];
2028
- const backupStyles = backupStateStyler ? backupStateStyler.buildStyles(params, errors) : {};
2029
- return stateStyler ? stateStyler.buildStyles(params, errors) : backupStyles;
2460
+ let styler = this._stateStyles.get('*');
2461
+ if (stateName !== undefined) {
2462
+ styler = this._stateStyles.get(stateName === null || stateName === void 0 ? void 0 : stateName.toString()) || styler;
2463
+ }
2464
+ return styler ? styler.buildStyles(params, errors) : new Map();
2030
2465
  }
2031
2466
  build(driver, element, currentState, nextState, enterClassName, leaveClassName, currentOptions, nextOptions, subInstructions, skipAstBuild) {
2467
+ var _a;
2032
2468
  const errors = [];
2033
2469
  const transitionAnimationParams = this.ast.options && this.ast.options.params || EMPTY_OBJECT;
2034
2470
  const currentAnimationParams = currentOptions && currentOptions.params || EMPTY_OBJECT;
@@ -2039,7 +2475,10 @@ class AnimationTransitionFactory {
2039
2475
  const preStyleMap = new Map();
2040
2476
  const postStyleMap = new Map();
2041
2477
  const isRemoval = nextState === 'void';
2042
- const animationOptions = { params: Object.assign(Object.assign({}, transitionAnimationParams), nextAnimationParams) };
2478
+ const animationOptions = {
2479
+ params: applyParamDefaults(nextAnimationParams, transitionAnimationParams),
2480
+ delay: (_a = this.ast.options) === null || _a === void 0 ? void 0 : _a.delay,
2481
+ };
2043
2482
  const timelines = skipAstBuild ?
2044
2483
  [] :
2045
2484
  buildAnimationTimelines(driver, element, this.ast.animation, enterClassName, leaveClassName, currentStateStyles, nextStateStyles, animationOptions, subInstructions, errors);
@@ -2052,10 +2491,10 @@ class AnimationTransitionFactory {
2052
2491
  }
2053
2492
  timelines.forEach(tl => {
2054
2493
  const elm = tl.element;
2055
- const preProps = getOrSetAsInMap(preStyleMap, elm, {});
2056
- tl.preStyleProps.forEach(prop => preProps[prop] = true);
2057
- const postProps = getOrSetAsInMap(postStyleMap, elm, {});
2058
- 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));
2059
2498
  if (elm !== element) {
2060
2499
  queriedElements.add(elm);
2061
2500
  }
@@ -2067,6 +2506,15 @@ class AnimationTransitionFactory {
2067
2506
  function oneOrMoreTransitionsMatch(matchFns, currentState, nextState, element, params) {
2068
2507
  return matchFns.some(fn => fn(currentState, nextState, element, params));
2069
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
+ }
2070
2518
  class AnimationStateStyles {
2071
2519
  constructor(styles, defaultParams, normalizer) {
2072
2520
  this.styles = styles;
@@ -2074,25 +2522,23 @@ class AnimationStateStyles {
2074
2522
  this.normalizer = normalizer;
2075
2523
  }
2076
2524
  buildStyles(params, errors) {
2077
- const finalStyles = {};
2525
+ const finalStyles = new Map();
2078
2526
  const combinedParams = copyObj(this.defaultParams);
2079
2527
  Object.keys(params).forEach(key => {
2080
2528
  const value = params[key];
2081
- if (value != null) {
2529
+ if (value !== null) {
2082
2530
  combinedParams[key] = value;
2083
2531
  }
2084
2532
  });
2085
2533
  this.styles.styles.forEach(value => {
2086
2534
  if (typeof value !== 'string') {
2087
- const styleObj = value;
2088
- Object.keys(styleObj).forEach(prop => {
2089
- let val = styleObj[prop];
2090
- if (val.length > 1) {
2535
+ value.forEach((val, prop) => {
2536
+ if (val) {
2091
2537
  val = interpolateParams(val, combinedParams, errors);
2092
2538
  }
2093
2539
  const normalizedProp = this.normalizer.normalizePropertyName(prop, errors);
2094
2540
  val = this.normalizer.normalizeStyleValue(prop, normalizedProp, val, errors);
2095
- finalStyles[normalizedProp] = val;
2541
+ finalStyles.set(normalizedProp, val);
2096
2542
  });
2097
2543
  }
2098
2544
  });
@@ -2109,10 +2555,10 @@ class AnimationTrigger {
2109
2555
  this.ast = ast;
2110
2556
  this._normalizer = _normalizer;
2111
2557
  this.transitionFactories = [];
2112
- this.states = {};
2558
+ this.states = new Map();
2113
2559
  ast.states.forEach(ast => {
2114
2560
  const defaultParams = (ast.options && ast.options.params) || {};
2115
- this.states[ast.name] = new AnimationStateStyles(ast.style, defaultParams, _normalizer);
2561
+ this.states.set(ast.name, new AnimationStateStyles(ast.style, defaultParams, _normalizer));
2116
2562
  });
2117
2563
  balanceProperties(this.states, 'true', '1');
2118
2564
  balanceProperties(this.states, 'false', '0');
@@ -2145,14 +2591,14 @@ function createFallbackTransition(triggerName, states, normalizer) {
2145
2591
  };
2146
2592
  return new AnimationTransitionFactory(triggerName, transition, states);
2147
2593
  }
2148
- function balanceProperties(obj, key1, key2) {
2149
- if (obj.hasOwnProperty(key1)) {
2150
- if (!obj.hasOwnProperty(key2)) {
2151
- 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));
2152
2598
  }
2153
2599
  }
2154
- else if (obj.hasOwnProperty(key2)) {
2155
- obj[key1] = obj[key2];
2600
+ else if (stateMap.has(key2)) {
2601
+ stateMap.set(key1, stateMap.get(key2));
2156
2602
  }
2157
2603
  }
2158
2604
 
@@ -2169,55 +2615,59 @@ class TimelineAnimationEngine {
2169
2615
  this.bodyNode = bodyNode;
2170
2616
  this._driver = _driver;
2171
2617
  this._normalizer = _normalizer;
2172
- this._animations = {};
2173
- this._playersById = {};
2618
+ this._animations = new Map();
2619
+ this._playersById = new Map();
2174
2620
  this.players = [];
2175
2621
  }
2176
2622
  register(id, metadata) {
2177
2623
  const errors = [];
2178
- const ast = buildAnimationAst(this._driver, metadata, errors);
2624
+ const warnings = [];
2625
+ const ast = buildAnimationAst(this._driver, metadata, errors, warnings);
2179
2626
  if (errors.length) {
2180
- throw new Error(`Unable to build the animation due to the following errors: ${errors.join('\n')}`);
2627
+ throw registerFailed(errors);
2181
2628
  }
2182
2629
  else {
2183
- this._animations[id] = ast;
2630
+ if (warnings.length) {
2631
+ warnRegister(warnings);
2632
+ }
2633
+ this._animations.set(id, ast);
2184
2634
  }
2185
2635
  }
2186
2636
  _buildPlayer(i, preStyles, postStyles) {
2187
2637
  const element = i.element;
2188
- 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);
2189
2639
  return this._driver.animate(element, keyframes, i.duration, i.delay, i.easing, [], true);
2190
2640
  }
2191
2641
  create(id, element, options = {}) {
2192
2642
  const errors = [];
2193
- const ast = this._animations[id];
2643
+ const ast = this._animations.get(id);
2194
2644
  let instructions;
2195
2645
  const autoStylesMap = new Map();
2196
2646
  if (ast) {
2197
- 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);
2198
2648
  instructions.forEach(inst => {
2199
- const styles = getOrSetAsInMap(autoStylesMap, inst.element, {});
2200
- 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));
2201
2651
  });
2202
2652
  }
2203
2653
  else {
2204
- errors.push('The requested animation doesn\'t exist or has already been destroyed');
2654
+ errors.push(missingOrDestroyedAnimation());
2205
2655
  instructions = [];
2206
2656
  }
2207
2657
  if (errors.length) {
2208
- throw new Error(`Unable to create the animation due to the following errors: ${errors.join('\n')}`);
2658
+ throw createAnimationFailed(errors);
2209
2659
  }
2210
2660
  autoStylesMap.forEach((styles, element) => {
2211
- Object.keys(styles).forEach(prop => {
2212
- styles[prop] = this._driver.computeStyle(element, prop, AUTO_STYLE);
2661
+ styles.forEach((_, prop) => {
2662
+ styles.set(prop, this._driver.computeStyle(element, prop, AUTO_STYLE));
2213
2663
  });
2214
2664
  });
2215
2665
  const players = instructions.map(i => {
2216
2666
  const styles = autoStylesMap.get(i.element);
2217
- return this._buildPlayer(i, {}, styles);
2667
+ return this._buildPlayer(i, new Map(), styles);
2218
2668
  });
2219
2669
  const player = optimizeGroupPlayer(players);
2220
- this._playersById[id] = player;
2670
+ this._playersById.set(id, player);
2221
2671
  player.onDestroy(() => this.destroy(id));
2222
2672
  this.players.push(player);
2223
2673
  return player;
@@ -2225,16 +2675,16 @@ class TimelineAnimationEngine {
2225
2675
  destroy(id) {
2226
2676
  const player = this._getPlayer(id);
2227
2677
  player.destroy();
2228
- delete this._playersById[id];
2678
+ this._playersById.delete(id);
2229
2679
  const index = this.players.indexOf(player);
2230
2680
  if (index >= 0) {
2231
2681
  this.players.splice(index, 1);
2232
2682
  }
2233
2683
  }
2234
2684
  _getPlayer(id) {
2235
- const player = this._playersById[id];
2685
+ const player = this._playersById.get(id);
2236
2686
  if (!player) {
2237
- throw new Error(`Unable to find the timeline player referenced by ${id}`);
2687
+ throw missingPlayer(id);
2238
2688
  }
2239
2689
  return player;
2240
2690
  }
@@ -2354,30 +2804,30 @@ class AnimationTransitionNamespace {
2354
2804
  this.hostElement = hostElement;
2355
2805
  this._engine = _engine;
2356
2806
  this.players = [];
2357
- this._triggers = {};
2807
+ this._triggers = new Map();
2358
2808
  this._queue = [];
2359
2809
  this._elementListeners = new Map();
2360
2810
  this._hostClassName = 'ng-tns-' + id;
2361
2811
  addClass(hostElement, this._hostClassName);
2362
2812
  }
2363
2813
  listen(element, name, phase, callback) {
2364
- if (!this._triggers.hasOwnProperty(name)) {
2365
- throw new Error(`Unable to listen on the animation trigger event "${phase}" because the animation trigger "${name}" doesn\'t exist!`);
2814
+ if (!this._triggers.has(name)) {
2815
+ throw missingTrigger(phase, name);
2366
2816
  }
2367
2817
  if (phase == null || phase.length == 0) {
2368
- throw new Error(`Unable to listen on the animation trigger "${name}" because the provided event is undefined!`);
2818
+ throw missingEvent(name);
2369
2819
  }
2370
2820
  if (!isTriggerEventValid(phase)) {
2371
- throw new Error(`The provided animation trigger event "${phase}" for the animation trigger "${name}" is not supported!`);
2821
+ throw unsupportedTriggerEvent(phase, name);
2372
2822
  }
2373
- const listeners = getOrSetAsInMap(this._elementListeners, element, []);
2823
+ const listeners = getOrSetDefaultValue(this._elementListeners, element, []);
2374
2824
  const data = { name, phase, callback };
2375
2825
  listeners.push(data);
2376
- const triggersWithStates = getOrSetAsInMap(this._engine.statesByElement, element, {});
2377
- if (!triggersWithStates.hasOwnProperty(name)) {
2826
+ const triggersWithStates = getOrSetDefaultValue(this._engine.statesByElement, element, new Map());
2827
+ if (!triggersWithStates.has(name)) {
2378
2828
  addClass(element, NG_TRIGGER_CLASSNAME);
2379
2829
  addClass(element, NG_TRIGGER_CLASSNAME + '-' + name);
2380
- triggersWithStates[name] = DEFAULT_STATE_VALUE;
2830
+ triggersWithStates.set(name, DEFAULT_STATE_VALUE);
2381
2831
  }
2382
2832
  return () => {
2383
2833
  // the event listener is removed AFTER the flush has occurred such
@@ -2388,26 +2838,26 @@ class AnimationTransitionNamespace {
2388
2838
  if (index >= 0) {
2389
2839
  listeners.splice(index, 1);
2390
2840
  }
2391
- if (!this._triggers[name]) {
2392
- delete triggersWithStates[name];
2841
+ if (!this._triggers.has(name)) {
2842
+ triggersWithStates.delete(name);
2393
2843
  }
2394
2844
  });
2395
2845
  };
2396
2846
  }
2397
2847
  register(name, ast) {
2398
- if (this._triggers[name]) {
2848
+ if (this._triggers.has(name)) {
2399
2849
  // throw
2400
2850
  return false;
2401
2851
  }
2402
2852
  else {
2403
- this._triggers[name] = ast;
2853
+ this._triggers.set(name, ast);
2404
2854
  return true;
2405
2855
  }
2406
2856
  }
2407
2857
  _getTrigger(name) {
2408
- const trigger = this._triggers[name];
2858
+ const trigger = this._triggers.get(name);
2409
2859
  if (!trigger) {
2410
- throw new Error(`The provided animation trigger "${name}" has not been registered!`);
2860
+ throw unregisteredTrigger(name);
2411
2861
  }
2412
2862
  return trigger;
2413
2863
  }
@@ -2418,15 +2868,15 @@ class AnimationTransitionNamespace {
2418
2868
  if (!triggersWithStates) {
2419
2869
  addClass(element, NG_TRIGGER_CLASSNAME);
2420
2870
  addClass(element, NG_TRIGGER_CLASSNAME + '-' + triggerName);
2421
- this._engine.statesByElement.set(element, triggersWithStates = {});
2871
+ this._engine.statesByElement.set(element, triggersWithStates = new Map());
2422
2872
  }
2423
- let fromState = triggersWithStates[triggerName];
2873
+ let fromState = triggersWithStates.get(triggerName);
2424
2874
  const toState = new StateValue(value, this.id);
2425
2875
  const isObj = value && value.hasOwnProperty('value');
2426
2876
  if (!isObj && fromState) {
2427
2877
  toState.absorbOptions(fromState.options);
2428
2878
  }
2429
- triggersWithStates[triggerName] = toState;
2879
+ triggersWithStates.set(triggerName, toState);
2430
2880
  if (!fromState) {
2431
2881
  fromState = DEFAULT_STATE_VALUE;
2432
2882
  }
@@ -2456,7 +2906,7 @@ class AnimationTransitionNamespace {
2456
2906
  }
2457
2907
  return;
2458
2908
  }
2459
- const playersOnElement = getOrSetAsInMap(this._engine.playersByElement, element, []);
2909
+ const playersOnElement = getOrSetDefaultValue(this._engine.playersByElement, element, []);
2460
2910
  playersOnElement.forEach(player => {
2461
2911
  // only remove the player if it is queued on the EXACT same trigger/namespace
2462
2912
  // we only also deal with queued players here because if the animation has
@@ -2500,10 +2950,8 @@ class AnimationTransitionNamespace {
2500
2950
  return player;
2501
2951
  }
2502
2952
  deregister(name) {
2503
- delete this._triggers[name];
2504
- this._engine.statesByElement.forEach((stateMap, element) => {
2505
- delete stateMap[name];
2506
- });
2953
+ this._triggers.delete(name);
2954
+ this._engine.statesByElement.forEach(stateMap => stateMap.delete(name));
2507
2955
  this._elementListeners.forEach((listeners, element) => {
2508
2956
  this._elementListeners.set(element, listeners.filter(entry => {
2509
2957
  return entry.name != name;
@@ -2546,11 +2994,11 @@ class AnimationTransitionNamespace {
2546
2994
  const previousTriggersValues = new Map();
2547
2995
  if (triggerStates) {
2548
2996
  const players = [];
2549
- Object.keys(triggerStates).forEach(triggerName => {
2550
- previousTriggersValues.set(triggerName, triggerStates[triggerName].value);
2997
+ triggerStates.forEach((state, triggerName) => {
2998
+ previousTriggersValues.set(triggerName, state.value);
2551
2999
  // this check is here in the event that an element is removed
2552
3000
  // twice (both on the host level and the component level)
2553
- if (this._triggers[triggerName]) {
3001
+ if (this._triggers.has(triggerName)) {
2554
3002
  const player = this.trigger(element, triggerName, VOID_VALUE, defaultToFallback);
2555
3003
  if (player) {
2556
3004
  players.push(player);
@@ -2579,9 +3027,9 @@ class AnimationTransitionNamespace {
2579
3027
  if (visitedTriggers.has(triggerName))
2580
3028
  return;
2581
3029
  visitedTriggers.add(triggerName);
2582
- const trigger = this._triggers[triggerName];
3030
+ const trigger = this._triggers.get(triggerName);
2583
3031
  const transition = trigger.fallbackTransition;
2584
- const fromState = elementStates[triggerName] || DEFAULT_STATE_VALUE;
3032
+ const fromState = elementStates.get(triggerName) || DEFAULT_STATE_VALUE;
2585
3033
  const toState = new StateValue(VOID_VALUE);
2586
3034
  const player = new TransitionAnimationPlayer(this.id, triggerName, element);
2587
3035
  this._engine.totalQueuedPlayers++;
@@ -2763,25 +3211,37 @@ class TransitionAnimationEngine {
2763
3211
  return this._namespaceLookup[namespaceId] = ns;
2764
3212
  }
2765
3213
  _balanceNamespaceList(ns, hostElement) {
2766
- const limit = this._namespaceList.length - 1;
3214
+ const namespaceList = this._namespaceList;
3215
+ const namespacesByHostElement = this.namespacesByHostElement;
3216
+ const limit = namespaceList.length - 1;
2767
3217
  if (limit >= 0) {
2768
3218
  let found = false;
2769
- for (let i = limit; i >= 0; i--) {
2770
- const nextNamespace = this._namespaceList[i];
2771
- if (this.driver.containsElement(nextNamespace.hostElement, hostElement)) {
2772
- this._namespaceList.splice(i + 1, 0, ns);
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);
2773
3229
  found = true;
2774
3230
  break;
2775
3231
  }
3232
+ ancestor = this.driver.getParentElement(ancestor);
2776
3233
  }
2777
3234
  if (!found) {
2778
- this._namespaceList.splice(0, 0, ns);
3235
+ // No namespace exists that is an ancestor of `ns`, so `ns` is inserted at the front to
3236
+ // ensure that any existing descendants are ordered after `ns`, retaining the desired
3237
+ // top-down ordering.
3238
+ namespaceList.unshift(ns);
2779
3239
  }
2780
3240
  }
2781
3241
  else {
2782
- this._namespaceList.push(ns);
3242
+ namespaceList.push(ns);
2783
3243
  }
2784
- this.namespacesByHostElement.set(hostElement, ns);
3244
+ namespacesByHostElement.set(hostElement, ns);
2785
3245
  return ns;
2786
3246
  }
2787
3247
  register(namespaceId, hostElement) {
@@ -2823,11 +3283,9 @@ class TransitionAnimationEngine {
2823
3283
  const namespaces = new Set();
2824
3284
  const elementStates = this.statesByElement.get(element);
2825
3285
  if (elementStates) {
2826
- const keys = Object.keys(elementStates);
2827
- for (let i = 0; i < keys.length; i++) {
2828
- const nsId = elementStates[keys[i]].namespaceId;
2829
- if (nsId) {
2830
- const ns = this._fetchNamespace(nsId);
3286
+ for (let stateValue of elementStates.values()) {
3287
+ if (stateValue.namespaceId) {
3288
+ const ns = this._fetchNamespace(stateValue.namespaceId);
2831
3289
  if (ns) {
2832
3290
  namespaces.add(ns);
2833
3291
  }
@@ -3048,7 +3506,7 @@ class TransitionAnimationEngine {
3048
3506
  }
3049
3507
  }
3050
3508
  reportError(errors) {
3051
- throw new Error(`Unable to process animations due to the following failed trigger transitions\n ${errors.join('\n')}`);
3509
+ throw triggerTransitionsFailed(errors);
3052
3510
  }
3053
3511
  _flushAnimations(cleanupFns, microtaskId) {
3054
3512
  const subTimelines = new ElementInstructionMap();
@@ -3135,8 +3593,10 @@ class TransitionAnimationEngine {
3135
3593
  // we need to restore the previous trigger value since the element has
3136
3594
  // only been moved and hasn't actually left the DOM
3137
3595
  const triggersWithStates = this.statesByElement.get(entry.element);
3138
- if (triggersWithStates && triggersWithStates[entry.triggerName]) {
3139
- triggersWithStates[entry.triggerName].value = previousValue;
3596
+ if (triggersWithStates && triggersWithStates.has(entry.triggerName)) {
3597
+ const state = triggersWithStates.get(entry.triggerName);
3598
+ state.value = previousValue;
3599
+ triggersWithStates.set(entry.triggerName, state);
3140
3600
  }
3141
3601
  }
3142
3602
  player.destroy();
@@ -3186,32 +3646,29 @@ class TransitionAnimationEngine {
3186
3646
  subTimelines.append(element, instruction.timelines);
3187
3647
  const tuple = { instruction, player, element };
3188
3648
  queuedInstructions.push(tuple);
3189
- instruction.queriedElements.forEach(element => getOrSetAsInMap(queriedElements, element, []).push(player));
3649
+ instruction.queriedElements.forEach(element => getOrSetDefaultValue(queriedElements, element, []).push(player));
3190
3650
  instruction.preStyleProps.forEach((stringMap, element) => {
3191
- const props = Object.keys(stringMap);
3192
- if (props.length) {
3651
+ if (stringMap.size) {
3193
3652
  let setVal = allPreStyleElements.get(element);
3194
3653
  if (!setVal) {
3195
3654
  allPreStyleElements.set(element, setVal = new Set());
3196
3655
  }
3197
- props.forEach(prop => setVal.add(prop));
3656
+ stringMap.forEach((_, prop) => setVal.add(prop));
3198
3657
  }
3199
3658
  });
3200
3659
  instruction.postStyleProps.forEach((stringMap, element) => {
3201
- const props = Object.keys(stringMap);
3202
3660
  let setVal = allPostStyleElements.get(element);
3203
3661
  if (!setVal) {
3204
3662
  allPostStyleElements.set(element, setVal = new Set());
3205
3663
  }
3206
- props.forEach(prop => setVal.add(prop));
3664
+ stringMap.forEach((_, prop) => setVal.add(prop));
3207
3665
  });
3208
3666
  });
3209
3667
  }
3210
3668
  if (erroneousTransitions.length) {
3211
3669
  const errors = [];
3212
3670
  erroneousTransitions.forEach(instruction => {
3213
- errors.push(`@${instruction.triggerName} has failed due to:\n`);
3214
- instruction.errors.forEach(error => errors.push(`- ${error}\n`));
3671
+ errors.push(transitionFailed(instruction.triggerName, instruction.errors));
3215
3672
  });
3216
3673
  allPlayers.forEach(player => player.destroy());
3217
3674
  this.reportError(errors);
@@ -3233,7 +3690,7 @@ class TransitionAnimationEngine {
3233
3690
  const element = player.element;
3234
3691
  const previousPlayers = this._getPreviousPlayers(element, false, player.namespaceId, player.triggerName, null);
3235
3692
  previousPlayers.forEach(prevPlayer => {
3236
- getOrSetAsInMap(allPreviousPlayersMap, element, []).push(prevPlayer);
3693
+ getOrSetDefaultValue(allPreviousPlayersMap, element, []).push(prevPlayer);
3237
3694
  prevPlayer.destroy();
3238
3695
  });
3239
3696
  });
@@ -3261,9 +3718,10 @@ class TransitionAnimationEngine {
3261
3718
  cloakAndComputeStyles(preStylesMap, this.driver, new Set(nodes), allPreStyleElements, ɵPRE_STYLE);
3262
3719
  });
3263
3720
  replaceNodes.forEach(node => {
3721
+ var _a, _b;
3264
3722
  const post = postStylesMap.get(node);
3265
3723
  const pre = preStylesMap.get(node);
3266
- postStylesMap.set(node, Object.assign(Object.assign({}, post), pre));
3724
+ 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 : [])]));
3267
3725
  });
3268
3726
  const rootPlayers = [];
3269
3727
  const subPlayers = [];
@@ -3457,7 +3915,7 @@ class TransitionAnimationEngine {
3457
3915
  for (const timelineInstruction of instruction.timelines) {
3458
3916
  const element = timelineInstruction.element;
3459
3917
  const isQueriedElement = element !== rootElement;
3460
- const players = getOrSetAsInMap(allPreviousPlayersMap, element, []);
3918
+ const players = getOrSetDefaultValue(allPreviousPlayersMap, element, []);
3461
3919
  const previousPlayers = this._getPreviousPlayers(element, isQueriedElement, targetNameSpaceId, targetTriggerName, instruction.toState);
3462
3920
  previousPlayers.forEach(player => {
3463
3921
  const realPlayer = player.getRealPlayer();
@@ -3500,7 +3958,7 @@ class TransitionAnimationEngine {
3500
3958
  });
3501
3959
  const preStyles = preStylesMap.get(element);
3502
3960
  const postStyles = postStylesMap.get(element);
3503
- const keyframes = normalizeKeyframes(this.driver, this._normalizer, element, timelineInstruction.keyframes, preStyles, postStyles);
3961
+ const keyframes = normalizeKeyframes$1(this.driver, this._normalizer, element, timelineInstruction.keyframes, preStyles, postStyles);
3504
3962
  const player = this._buildPlayer(timelineInstruction, keyframes, previousPlayers);
3505
3963
  // this means that this particular player belongs to a sub trigger. It is
3506
3964
  // important that we match this player up with the corresponding (@trigger.listener)
@@ -3515,7 +3973,7 @@ class TransitionAnimationEngine {
3515
3973
  return player;
3516
3974
  });
3517
3975
  allQueriedPlayers.forEach(player => {
3518
- getOrSetAsInMap(this.playersByQueriedElement, player.element, []).push(player);
3976
+ getOrSetDefaultValue(this.playersByQueriedElement, player.element, []).push(player);
3519
3977
  player.onDone(() => deleteOrUnsetInMap(this.playersByQueriedElement, player.element, player));
3520
3978
  });
3521
3979
  allConsumedElements.forEach(element => addClass(element, NG_ANIMATING_CLASSNAME));
@@ -3527,7 +3985,7 @@ class TransitionAnimationEngine {
3527
3985
  // this basically makes all of the callbacks for sub element animations
3528
3986
  // be dependent on the upper players for when they finish
3529
3987
  allSubElements.forEach(element => {
3530
- getOrSetAsInMap(skippedPlayersMap, element, []).push(player);
3988
+ getOrSetDefaultValue(skippedPlayersMap, element, []).push(player);
3531
3989
  });
3532
3990
  return player;
3533
3991
  }
@@ -3547,7 +4005,7 @@ class TransitionAnimationPlayer {
3547
4005
  this.element = element;
3548
4006
  this._player = new NoopAnimationPlayer();
3549
4007
  this._containsRealPlayer = false;
3550
- this._queuedCallbacks = {};
4008
+ this._queuedCallbacks = new Map();
3551
4009
  this.destroyed = false;
3552
4010
  this.markedForDestroy = false;
3553
4011
  this.disabled = false;
@@ -3558,10 +4016,10 @@ class TransitionAnimationPlayer {
3558
4016
  if (this._containsRealPlayer)
3559
4017
  return;
3560
4018
  this._player = player;
3561
- Object.keys(this._queuedCallbacks).forEach(phase => {
3562
- this._queuedCallbacks[phase].forEach(callback => listenOnPlayer(player, phase, undefined, callback));
4019
+ this._queuedCallbacks.forEach((callbacks, phase) => {
4020
+ callbacks.forEach(callback => listenOnPlayer(player, phase, undefined, callback));
3563
4021
  });
3564
- this._queuedCallbacks = {};
4022
+ this._queuedCallbacks.clear();
3565
4023
  this._containsRealPlayer = true;
3566
4024
  this.overrideTotalTime(player.totalTime);
3567
4025
  this.queued = false;
@@ -3581,7 +4039,7 @@ class TransitionAnimationPlayer {
3581
4039
  player.onDestroy(() => this.destroy());
3582
4040
  }
3583
4041
  _queueEvent(name, callback) {
3584
- getOrSetAsInMap(this._queuedCallbacks, name, []).push(callback);
4042
+ getOrSetDefaultValue(this._queuedCallbacks, name, []).push(callback);
3585
4043
  }
3586
4044
  onDone(fn) {
3587
4045
  if (this.queued) {
@@ -3643,29 +4101,14 @@ class TransitionAnimationPlayer {
3643
4101
  }
3644
4102
  }
3645
4103
  function deleteOrUnsetInMap(map, key, value) {
3646
- let currentValues;
3647
- if (map instanceof Map) {
3648
- currentValues = map.get(key);
3649
- if (currentValues) {
3650
- if (currentValues.length) {
3651
- const index = currentValues.indexOf(value);
3652
- currentValues.splice(index, 1);
3653
- }
3654
- if (currentValues.length == 0) {
3655
- map.delete(key);
3656
- }
4104
+ let currentValues = map.get(key);
4105
+ if (currentValues) {
4106
+ if (currentValues.length) {
4107
+ const index = currentValues.indexOf(value);
4108
+ currentValues.splice(index, 1);
3657
4109
  }
3658
- }
3659
- else {
3660
- currentValues = map[key];
3661
- if (currentValues) {
3662
- if (currentValues.length) {
3663
- const index = currentValues.indexOf(value);
3664
- currentValues.splice(index, 1);
3665
- }
3666
- if (currentValues.length == 0) {
3667
- delete map[key];
3668
- }
4110
+ if (currentValues.length == 0) {
4111
+ map.delete(key);
3669
4112
  }
3670
4113
  }
3671
4114
  return currentValues;
@@ -3692,9 +4135,10 @@ function cloakAndComputeStyles(valuesMap, driver, elements, elementPropsMap, def
3692
4135
  elements.forEach(element => cloakVals.push(cloakElement(element)));
3693
4136
  const failedElements = [];
3694
4137
  elementPropsMap.forEach((props, element) => {
3695
- const styles = {};
4138
+ const styles = new Map();
3696
4139
  props.forEach(prop => {
3697
- const value = styles[prop] = driver.computeStyle(element, prop, defaultStyle);
4140
+ const value = driver.computeStyle(element, prop, defaultStyle);
4141
+ styles.set(prop, value);
3698
4142
  // there is no easy way to detect this because a sub element could be removed
3699
4143
  // by a parent animation element being detached.
3700
4144
  if (!value || value.length == 0) {
@@ -3826,9 +4270,13 @@ class AnimationEngine {
3826
4270
  let trigger = this._triggerCache[cacheKey];
3827
4271
  if (!trigger) {
3828
4272
  const errors = [];
3829
- const ast = buildAnimationAst(this._driver, metadata, errors);
4273
+ const warnings = [];
4274
+ const ast = buildAnimationAst(this._driver, metadata, errors, warnings);
3830
4275
  if (errors.length) {
3831
- throw new Error(`The animation trigger "${name}" has failed to build due to the following errors:\n - ${errors.join('\n - ')}`);
4276
+ throw triggerBuildFailed(name, errors);
4277
+ }
4278
+ if (warnings.length) {
4279
+ warnTriggerBuild(name, warnings);
3832
4280
  }
3833
4281
  trigger = buildTrigger(name, ast, this._normalizer);
3834
4282
  this._triggerCache[cacheKey] = trigger;
@@ -3880,13 +4328,6 @@ class AnimationEngine {
3880
4328
  }
3881
4329
  }
3882
4330
 
3883
- /**
3884
- * @license
3885
- * Copyright Google LLC All Rights Reserved.
3886
- *
3887
- * Use of this source code is governed by an MIT-style license that can be
3888
- * found in the LICENSE file at https://angular.io/license
3889
- */
3890
4331
  /**
3891
4332
  * Returns an instance of `SpecialCasedStyles` if and when any special (non animateable) styles are
3892
4333
  * detected.
@@ -3907,7 +4348,7 @@ function packageNonAnimatableStyles(element, styles) {
3907
4348
  endStyles = filterNonAnimatableStyles(styles[styles.length - 1]);
3908
4349
  }
3909
4350
  }
3910
- else if (styles) {
4351
+ else if (styles instanceof Map) {
3911
4352
  startStyles = filterNonAnimatableStyles(styles);
3912
4353
  }
3913
4354
  return (startStyles || endStyles) ? new SpecialCasedStyles(element, startStyles, endStyles) :
@@ -3929,7 +4370,7 @@ class SpecialCasedStyles {
3929
4370
  this._state = 0 /* Pending */;
3930
4371
  let initialStyles = SpecialCasedStyles.initialStylesByElement.get(_element);
3931
4372
  if (!initialStyles) {
3932
- SpecialCasedStyles.initialStylesByElement.set(_element, initialStyles = {});
4373
+ SpecialCasedStyles.initialStylesByElement.set(_element, initialStyles = new Map());
3933
4374
  }
3934
4375
  this._initialStyles = initialStyles;
3935
4376
  }
@@ -3972,454 +4413,18 @@ class SpecialCasedStyles {
3972
4413
  SpecialCasedStyles.initialStylesByElement = ( /* @__PURE__ */new WeakMap());
3973
4414
  function filterNonAnimatableStyles(styles) {
3974
4415
  let result = null;
3975
- const props = Object.keys(styles);
3976
- for (let i = 0; i < props.length; i++) {
3977
- const prop = props[i];
4416
+ styles.forEach((val, prop) => {
3978
4417
  if (isNonAnimatableStyle(prop)) {
3979
- result = result || {};
3980
- result[prop] = styles[prop];
4418
+ result = result || new Map();
4419
+ result.set(prop, val);
3981
4420
  }
3982
- }
4421
+ });
3983
4422
  return result;
3984
4423
  }
3985
4424
  function isNonAnimatableStyle(prop) {
3986
4425
  return prop === 'display' || prop === 'position';
3987
4426
  }
3988
4427
 
3989
- /**
3990
- * @license
3991
- * Copyright Google LLC All Rights Reserved.
3992
- *
3993
- * Use of this source code is governed by an MIT-style license that can be
3994
- * found in the LICENSE file at https://angular.io/license
3995
- */
3996
- const ELAPSED_TIME_MAX_DECIMAL_PLACES = 3;
3997
- const ANIMATION_PROP = 'animation';
3998
- const ANIMATIONEND_EVENT = 'animationend';
3999
- const ONE_SECOND = 1000;
4000
- class ElementAnimationStyleHandler {
4001
- constructor(_element, _name, _duration, _delay, _easing, _fillMode, _onDoneFn) {
4002
- this._element = _element;
4003
- this._name = _name;
4004
- this._duration = _duration;
4005
- this._delay = _delay;
4006
- this._easing = _easing;
4007
- this._fillMode = _fillMode;
4008
- this._onDoneFn = _onDoneFn;
4009
- this._finished = false;
4010
- this._destroyed = false;
4011
- this._startTime = 0;
4012
- this._position = 0;
4013
- this._eventFn = (e) => this._handleCallback(e);
4014
- }
4015
- apply() {
4016
- applyKeyframeAnimation(this._element, `${this._duration}ms ${this._easing} ${this._delay}ms 1 normal ${this._fillMode} ${this._name}`);
4017
- addRemoveAnimationEvent(this._element, this._eventFn, false);
4018
- this._startTime = Date.now();
4019
- }
4020
- pause() {
4021
- playPauseAnimation(this._element, this._name, 'paused');
4022
- }
4023
- resume() {
4024
- playPauseAnimation(this._element, this._name, 'running');
4025
- }
4026
- setPosition(position) {
4027
- const index = findIndexForAnimation(this._element, this._name);
4028
- this._position = position * this._duration;
4029
- setAnimationStyle(this._element, 'Delay', `-${this._position}ms`, index);
4030
- }
4031
- getPosition() {
4032
- return this._position;
4033
- }
4034
- _handleCallback(event) {
4035
- const timestamp = event._ngTestManualTimestamp || Date.now();
4036
- const elapsedTime = parseFloat(event.elapsedTime.toFixed(ELAPSED_TIME_MAX_DECIMAL_PLACES)) * ONE_SECOND;
4037
- if (event.animationName == this._name &&
4038
- Math.max(timestamp - this._startTime, 0) >= this._delay && elapsedTime >= this._duration) {
4039
- this.finish();
4040
- }
4041
- }
4042
- finish() {
4043
- if (this._finished)
4044
- return;
4045
- this._finished = true;
4046
- this._onDoneFn();
4047
- addRemoveAnimationEvent(this._element, this._eventFn, true);
4048
- }
4049
- destroy() {
4050
- if (this._destroyed)
4051
- return;
4052
- this._destroyed = true;
4053
- this.finish();
4054
- removeKeyframeAnimation(this._element, this._name);
4055
- }
4056
- }
4057
- function playPauseAnimation(element, name, status) {
4058
- const index = findIndexForAnimation(element, name);
4059
- setAnimationStyle(element, 'PlayState', status, index);
4060
- }
4061
- function applyKeyframeAnimation(element, value) {
4062
- const anim = getAnimationStyle(element, '').trim();
4063
- let index = 0;
4064
- if (anim.length) {
4065
- index = countChars(anim, ',') + 1;
4066
- value = `${anim}, ${value}`;
4067
- }
4068
- setAnimationStyle(element, '', value);
4069
- return index;
4070
- }
4071
- function removeKeyframeAnimation(element, name) {
4072
- const anim = getAnimationStyle(element, '');
4073
- const tokens = anim.split(',');
4074
- const index = findMatchingTokenIndex(tokens, name);
4075
- if (index >= 0) {
4076
- tokens.splice(index, 1);
4077
- const newValue = tokens.join(',');
4078
- setAnimationStyle(element, '', newValue);
4079
- }
4080
- }
4081
- function findIndexForAnimation(element, value) {
4082
- const anim = getAnimationStyle(element, '');
4083
- if (anim.indexOf(',') > 0) {
4084
- const tokens = anim.split(',');
4085
- return findMatchingTokenIndex(tokens, value);
4086
- }
4087
- return findMatchingTokenIndex([anim], value);
4088
- }
4089
- function findMatchingTokenIndex(tokens, searchToken) {
4090
- for (let i = 0; i < tokens.length; i++) {
4091
- if (tokens[i].indexOf(searchToken) >= 0) {
4092
- return i;
4093
- }
4094
- }
4095
- return -1;
4096
- }
4097
- function addRemoveAnimationEvent(element, fn, doRemove) {
4098
- doRemove ? element.removeEventListener(ANIMATIONEND_EVENT, fn) :
4099
- element.addEventListener(ANIMATIONEND_EVENT, fn);
4100
- }
4101
- function setAnimationStyle(element, name, value, index) {
4102
- const prop = ANIMATION_PROP + name;
4103
- if (index != null) {
4104
- const oldValue = element.style[prop];
4105
- if (oldValue.length) {
4106
- const tokens = oldValue.split(',');
4107
- tokens[index] = value;
4108
- value = tokens.join(',');
4109
- }
4110
- }
4111
- element.style[prop] = value;
4112
- }
4113
- function getAnimationStyle(element, name) {
4114
- return element.style[ANIMATION_PROP + name] || '';
4115
- }
4116
- function countChars(value, char) {
4117
- let count = 0;
4118
- for (let i = 0; i < value.length; i++) {
4119
- const c = value.charAt(i);
4120
- if (c === char)
4121
- count++;
4122
- }
4123
- return count;
4124
- }
4125
-
4126
- const DEFAULT_FILL_MODE = 'forwards';
4127
- const DEFAULT_EASING = 'linear';
4128
- class CssKeyframesPlayer {
4129
- constructor(element, keyframes, animationName, _duration, _delay, easing, _finalStyles, _specialStyles) {
4130
- this.element = element;
4131
- this.keyframes = keyframes;
4132
- this.animationName = animationName;
4133
- this._duration = _duration;
4134
- this._delay = _delay;
4135
- this._finalStyles = _finalStyles;
4136
- this._specialStyles = _specialStyles;
4137
- this._onDoneFns = [];
4138
- this._onStartFns = [];
4139
- this._onDestroyFns = [];
4140
- this.currentSnapshot = {};
4141
- this._state = 0;
4142
- this.easing = easing || DEFAULT_EASING;
4143
- this.totalTime = _duration + _delay;
4144
- this._buildStyler();
4145
- }
4146
- onStart(fn) {
4147
- this._onStartFns.push(fn);
4148
- }
4149
- onDone(fn) {
4150
- this._onDoneFns.push(fn);
4151
- }
4152
- onDestroy(fn) {
4153
- this._onDestroyFns.push(fn);
4154
- }
4155
- destroy() {
4156
- this.init();
4157
- if (this._state >= 4 /* DESTROYED */)
4158
- return;
4159
- this._state = 4 /* DESTROYED */;
4160
- this._styler.destroy();
4161
- this._flushStartFns();
4162
- this._flushDoneFns();
4163
- if (this._specialStyles) {
4164
- this._specialStyles.destroy();
4165
- }
4166
- this._onDestroyFns.forEach(fn => fn());
4167
- this._onDestroyFns = [];
4168
- }
4169
- _flushDoneFns() {
4170
- this._onDoneFns.forEach(fn => fn());
4171
- this._onDoneFns = [];
4172
- }
4173
- _flushStartFns() {
4174
- this._onStartFns.forEach(fn => fn());
4175
- this._onStartFns = [];
4176
- }
4177
- finish() {
4178
- this.init();
4179
- if (this._state >= 3 /* FINISHED */)
4180
- return;
4181
- this._state = 3 /* FINISHED */;
4182
- this._styler.finish();
4183
- this._flushStartFns();
4184
- if (this._specialStyles) {
4185
- this._specialStyles.finish();
4186
- }
4187
- this._flushDoneFns();
4188
- }
4189
- setPosition(value) {
4190
- this._styler.setPosition(value);
4191
- }
4192
- getPosition() {
4193
- return this._styler.getPosition();
4194
- }
4195
- hasStarted() {
4196
- return this._state >= 2 /* STARTED */;
4197
- }
4198
- init() {
4199
- if (this._state >= 1 /* INITIALIZED */)
4200
- return;
4201
- this._state = 1 /* INITIALIZED */;
4202
- const elm = this.element;
4203
- this._styler.apply();
4204
- if (this._delay) {
4205
- this._styler.pause();
4206
- }
4207
- }
4208
- play() {
4209
- this.init();
4210
- if (!this.hasStarted()) {
4211
- this._flushStartFns();
4212
- this._state = 2 /* STARTED */;
4213
- if (this._specialStyles) {
4214
- this._specialStyles.start();
4215
- }
4216
- }
4217
- this._styler.resume();
4218
- }
4219
- pause() {
4220
- this.init();
4221
- this._styler.pause();
4222
- }
4223
- restart() {
4224
- this.reset();
4225
- this.play();
4226
- }
4227
- reset() {
4228
- this._state = 0 /* RESET */;
4229
- this._styler.destroy();
4230
- this._buildStyler();
4231
- this._styler.apply();
4232
- }
4233
- _buildStyler() {
4234
- this._styler = new ElementAnimationStyleHandler(this.element, this.animationName, this._duration, this._delay, this.easing, DEFAULT_FILL_MODE, () => this.finish());
4235
- }
4236
- /** @internal */
4237
- triggerCallback(phaseName) {
4238
- const methods = phaseName == 'start' ? this._onStartFns : this._onDoneFns;
4239
- methods.forEach(fn => fn());
4240
- methods.length = 0;
4241
- }
4242
- beforeDestroy() {
4243
- this.init();
4244
- const styles = {};
4245
- if (this.hasStarted()) {
4246
- const finished = this._state >= 3 /* FINISHED */;
4247
- Object.keys(this._finalStyles).forEach(prop => {
4248
- if (prop != 'offset') {
4249
- styles[prop] = finished ? this._finalStyles[prop] : computeStyle(this.element, prop);
4250
- }
4251
- });
4252
- }
4253
- this.currentSnapshot = styles;
4254
- }
4255
- }
4256
-
4257
- /**
4258
- * @license
4259
- * Copyright Google LLC All Rights Reserved.
4260
- *
4261
- * Use of this source code is governed by an MIT-style license that can be
4262
- * found in the LICENSE file at https://angular.io/license
4263
- */
4264
- class DirectStylePlayer extends NoopAnimationPlayer {
4265
- constructor(element, styles) {
4266
- super();
4267
- this.element = element;
4268
- this._startingStyles = {};
4269
- this.__initialized = false;
4270
- this._styles = hypenatePropsObject(styles);
4271
- }
4272
- init() {
4273
- if (this.__initialized || !this._startingStyles)
4274
- return;
4275
- this.__initialized = true;
4276
- Object.keys(this._styles).forEach(prop => {
4277
- this._startingStyles[prop] = this.element.style[prop];
4278
- });
4279
- super.init();
4280
- }
4281
- play() {
4282
- if (!this._startingStyles)
4283
- return;
4284
- this.init();
4285
- Object.keys(this._styles)
4286
- .forEach(prop => this.element.style.setProperty(prop, this._styles[prop]));
4287
- super.play();
4288
- }
4289
- destroy() {
4290
- if (!this._startingStyles)
4291
- return;
4292
- Object.keys(this._startingStyles).forEach(prop => {
4293
- const value = this._startingStyles[prop];
4294
- if (value) {
4295
- this.element.style.setProperty(prop, value);
4296
- }
4297
- else {
4298
- this.element.style.removeProperty(prop);
4299
- }
4300
- });
4301
- this._startingStyles = null;
4302
- super.destroy();
4303
- }
4304
- }
4305
-
4306
- const KEYFRAMES_NAME_PREFIX = 'gen_css_kf_';
4307
- const TAB_SPACE = ' ';
4308
- class CssKeyframesDriver {
4309
- constructor() {
4310
- this._count = 0;
4311
- }
4312
- validateStyleProperty(prop) {
4313
- return validateStyleProperty(prop);
4314
- }
4315
- matchesElement(_element, _selector) {
4316
- // This method is deprecated and no longer in use so we return false.
4317
- return false;
4318
- }
4319
- containsElement(elm1, elm2) {
4320
- return containsElement(elm1, elm2);
4321
- }
4322
- query(element, selector, multi) {
4323
- return invokeQuery(element, selector, multi);
4324
- }
4325
- computeStyle(element, prop, defaultValue) {
4326
- return window.getComputedStyle(element)[prop];
4327
- }
4328
- buildKeyframeElement(element, name, keyframes) {
4329
- keyframes = keyframes.map(kf => hypenatePropsObject(kf));
4330
- let keyframeStr = `@keyframes ${name} {\n`;
4331
- let tab = '';
4332
- keyframes.forEach(kf => {
4333
- tab = TAB_SPACE;
4334
- const offset = parseFloat(kf['offset']);
4335
- keyframeStr += `${tab}${offset * 100}% {\n`;
4336
- tab += TAB_SPACE;
4337
- Object.keys(kf).forEach(prop => {
4338
- const value = kf[prop];
4339
- switch (prop) {
4340
- case 'offset':
4341
- return;
4342
- case 'easing':
4343
- if (value) {
4344
- keyframeStr += `${tab}animation-timing-function: ${value};\n`;
4345
- }
4346
- return;
4347
- default:
4348
- keyframeStr += `${tab}${prop}: ${value};\n`;
4349
- return;
4350
- }
4351
- });
4352
- keyframeStr += `${tab}}\n`;
4353
- });
4354
- keyframeStr += `}\n`;
4355
- const kfElm = document.createElement('style');
4356
- kfElm.textContent = keyframeStr;
4357
- return kfElm;
4358
- }
4359
- animate(element, keyframes, duration, delay, easing, previousPlayers = [], scrubberAccessRequested) {
4360
- if ((typeof ngDevMode === 'undefined' || ngDevMode) && scrubberAccessRequested) {
4361
- notifyFaultyScrubber();
4362
- }
4363
- const previousCssKeyframePlayers = previousPlayers.filter(player => player instanceof CssKeyframesPlayer);
4364
- const previousStyles = {};
4365
- if (allowPreviousPlayerStylesMerge(duration, delay)) {
4366
- previousCssKeyframePlayers.forEach(player => {
4367
- let styles = player.currentSnapshot;
4368
- Object.keys(styles).forEach(prop => previousStyles[prop] = styles[prop]);
4369
- });
4370
- }
4371
- keyframes = balancePreviousStylesIntoKeyframes(element, keyframes, previousStyles);
4372
- const finalStyles = flattenKeyframesIntoStyles(keyframes);
4373
- // if there is no animation then there is no point in applying
4374
- // styles and waiting for an event to get fired. This causes lag.
4375
- // It's better to just directly apply the styles to the element
4376
- // via the direct styling animation player.
4377
- if (duration == 0) {
4378
- return new DirectStylePlayer(element, finalStyles);
4379
- }
4380
- const animationName = `${KEYFRAMES_NAME_PREFIX}${this._count++}`;
4381
- const kfElm = this.buildKeyframeElement(element, animationName, keyframes);
4382
- const nodeToAppendKfElm = findNodeToAppendKeyframeElement(element);
4383
- nodeToAppendKfElm.appendChild(kfElm);
4384
- const specialStyles = packageNonAnimatableStyles(element, keyframes);
4385
- const player = new CssKeyframesPlayer(element, keyframes, animationName, duration, delay, easing, finalStyles, specialStyles);
4386
- player.onDestroy(() => removeElement(kfElm));
4387
- return player;
4388
- }
4389
- }
4390
- function findNodeToAppendKeyframeElement(element) {
4391
- var _a;
4392
- const rootNode = (_a = element.getRootNode) === null || _a === void 0 ? void 0 : _a.call(element);
4393
- if (typeof ShadowRoot !== 'undefined' && rootNode instanceof ShadowRoot) {
4394
- return rootNode;
4395
- }
4396
- return document.head;
4397
- }
4398
- function flattenKeyframesIntoStyles(keyframes) {
4399
- let flatKeyframes = {};
4400
- if (keyframes) {
4401
- const kfs = Array.isArray(keyframes) ? keyframes : [keyframes];
4402
- kfs.forEach(kf => {
4403
- Object.keys(kf).forEach(prop => {
4404
- if (prop == 'offset' || prop == 'easing')
4405
- return;
4406
- flatKeyframes[prop] = kf[prop];
4407
- });
4408
- });
4409
- }
4410
- return flatKeyframes;
4411
- }
4412
- function removeElement(node) {
4413
- node.parentNode.removeChild(node);
4414
- }
4415
- let warningIssued = false;
4416
- function notifyFaultyScrubber() {
4417
- if (warningIssued)
4418
- return;
4419
- console.warn('@angular/animations: please load the web-animations.js polyfill to allow programmatic access...\n', ' visit https://bit.ly/IWukam to learn more about using the web-animation-js polyfill.');
4420
- warningIssued = true;
4421
- }
4422
-
4423
4428
  class WebAnimationsPlayer {
4424
4429
  constructor(element, keyframes, options, _specialStyles) {
4425
4430
  this.element = element;
@@ -4435,7 +4440,7 @@ class WebAnimationsPlayer {
4435
4440
  this._destroyed = false;
4436
4441
  this.time = 0;
4437
4442
  this.parentPlayer = null;
4438
- this.currentSnapshot = {};
4443
+ this.currentSnapshot = new Map();
4439
4444
  this._duration = options['duration'];
4440
4445
  this._delay = options['delay'] || 0;
4441
4446
  this.time = this._duration + this._delay;
@@ -4458,7 +4463,7 @@ class WebAnimationsPlayer {
4458
4463
  const keyframes = this.keyframes;
4459
4464
  this.domPlayer =
4460
4465
  this._triggerWebAnimation(this.element, keyframes, this.options);
4461
- this._finalKeyframe = keyframes.length ? keyframes[keyframes.length - 1] : {};
4466
+ this._finalKeyframe = keyframes.length ? keyframes[keyframes.length - 1] : new Map();
4462
4467
  this.domPlayer.addEventListener('finish', () => this._onFinish());
4463
4468
  }
4464
4469
  _preparePlayerBeforeStart() {
@@ -4470,11 +4475,18 @@ class WebAnimationsPlayer {
4470
4475
  this.domPlayer.pause();
4471
4476
  }
4472
4477
  }
4478
+ _convertKeyframesToObject(keyframes) {
4479
+ const kfs = [];
4480
+ keyframes.forEach(frame => {
4481
+ kfs.push(Object.fromEntries(frame));
4482
+ });
4483
+ return kfs;
4484
+ }
4473
4485
  /** @internal */
4474
4486
  _triggerWebAnimation(element, keyframes, options) {
4475
4487
  // jscompiler doesn't seem to know animate is a native property because it's not fully
4476
4488
  // supported yet across common browsers (we polyfill it for Edge/Safari) [CL #143630929]
4477
- return element['animate'](keyframes, options);
4489
+ return element['animate'](this._convertKeyframesToObject(keyframes), options);
4478
4490
  }
4479
4491
  onStart(fn) {
4480
4492
  this._onStartFns.push(fn);
@@ -4552,15 +4564,15 @@ class WebAnimationsPlayer {
4552
4564
  return this._delay + this._duration;
4553
4565
  }
4554
4566
  beforeDestroy() {
4555
- const styles = {};
4567
+ const styles = new Map();
4556
4568
  if (this.hasStarted()) {
4557
4569
  // note: this code is invoked only when the `play` function was called prior to this
4558
4570
  // (thus `hasStarted` returns true), this implies that the code that initializes
4559
4571
  // `_finalKeyframe` has also been executed and the non-null assertion can be safely used here
4560
4572
  const finalKeyframe = this._finalKeyframe;
4561
- Object.keys(finalKeyframe).forEach(prop => {
4562
- if (prop != 'offset') {
4563
- styles[prop] = this._finished ? finalKeyframe[prop] : computeStyle(this.element, prop);
4573
+ finalKeyframe.forEach((val, prop) => {
4574
+ if (prop !== 'offset') {
4575
+ styles.set(prop, this._finished ? val : computeStyle(this.element, prop));
4564
4576
  }
4565
4577
  });
4566
4578
  }
@@ -4568,20 +4580,24 @@ class WebAnimationsPlayer {
4568
4580
  }
4569
4581
  /** @internal */
4570
4582
  triggerCallback(phaseName) {
4571
- const methods = phaseName == 'start' ? this._onStartFns : this._onDoneFns;
4583
+ const methods = phaseName === 'start' ? this._onStartFns : this._onDoneFns;
4572
4584
  methods.forEach(fn => fn());
4573
4585
  methods.length = 0;
4574
4586
  }
4575
4587
  }
4576
4588
 
4577
4589
  class WebAnimationsDriver {
4578
- constructor() {
4579
- this._isNativeImpl = /\{\s*\[native\s+code\]\s*\}/.test(getElementAnimateFn().toString());
4580
- this._cssKeyframesDriver = new CssKeyframesDriver();
4581
- }
4582
4590
  validateStyleProperty(prop) {
4583
4591
  return validateStyleProperty(prop);
4584
4592
  }
4593
+ validateAnimatableStyleProperty(prop) {
4594
+ // Perform actual validation in dev mode only, in prod mode this check is a noop.
4595
+ if (ngDevMode) {
4596
+ const cssProp = camelCaseToDashCase(prop);
4597
+ return validateWebAnimatableStyleProperty(cssProp);
4598
+ }
4599
+ return true;
4600
+ }
4585
4601
  matchesElement(_element, _selector) {
4586
4602
  // This method is deprecated and no longer in use so we return false.
4587
4603
  return false;
@@ -4589,20 +4605,16 @@ class WebAnimationsDriver {
4589
4605
  containsElement(elm1, elm2) {
4590
4606
  return containsElement(elm1, elm2);
4591
4607
  }
4608
+ getParentElement(element) {
4609
+ return getParentElement(element);
4610
+ }
4592
4611
  query(element, selector, multi) {
4593
4612
  return invokeQuery(element, selector, multi);
4594
4613
  }
4595
4614
  computeStyle(element, prop, defaultValue) {
4596
4615
  return window.getComputedStyle(element)[prop];
4597
4616
  }
4598
- overrideWebAnimationsSupport(supported) {
4599
- this._isNativeImpl = supported;
4600
- }
4601
- animate(element, keyframes, duration, delay, easing, previousPlayers = [], scrubberAccessRequested) {
4602
- const useKeyframes = !scrubberAccessRequested && !this._isNativeImpl;
4603
- if (useKeyframes) {
4604
- return this._cssKeyframesDriver.animate(element, keyframes, duration, delay, easing, previousPlayers);
4605
- }
4617
+ animate(element, keyframes, duration, delay, easing, previousPlayers = []) {
4606
4618
  const fill = delay == 0 ? 'both' : 'forwards';
4607
4619
  const playerOptions = { duration, delay, fill };
4608
4620
  // we check for this to avoid having a null|undefined value be present
@@ -4610,26 +4622,19 @@ class WebAnimationsDriver {
4610
4622
  if (easing) {
4611
4623
  playerOptions['easing'] = easing;
4612
4624
  }
4613
- const previousStyles = {};
4625
+ const previousStyles = new Map();
4614
4626
  const previousWebAnimationPlayers = previousPlayers.filter(player => player instanceof WebAnimationsPlayer);
4615
4627
  if (allowPreviousPlayerStylesMerge(duration, delay)) {
4616
4628
  previousWebAnimationPlayers.forEach(player => {
4617
- let styles = player.currentSnapshot;
4618
- Object.keys(styles).forEach(prop => previousStyles[prop] = styles[prop]);
4629
+ player.currentSnapshot.forEach((val, prop) => previousStyles.set(prop, val));
4619
4630
  });
4620
4631
  }
4621
- keyframes = keyframes.map(styles => copyStyles(styles, false));
4622
- keyframes = balancePreviousStylesIntoKeyframes(element, keyframes, previousStyles);
4623
- const specialStyles = packageNonAnimatableStyles(element, keyframes);
4624
- return new WebAnimationsPlayer(element, keyframes, playerOptions, specialStyles);
4632
+ let _keyframes = normalizeKeyframes(keyframes).map(styles => copyStyles(styles));
4633
+ _keyframes = balancePreviousStylesIntoKeyframes(element, _keyframes, previousStyles);
4634
+ const specialStyles = packageNonAnimatableStyles(element, _keyframes);
4635
+ return new WebAnimationsPlayer(element, _keyframes, playerOptions, specialStyles);
4625
4636
  }
4626
4637
  }
4627
- function supportsWebAnimations() {
4628
- return typeof getElementAnimateFn() === 'function';
4629
- }
4630
- function getElementAnimateFn() {
4631
- return (isBrowser() && Element.prototype['animate']) || {};
4632
- }
4633
4638
 
4634
4639
  /**
4635
4640
  * @license
@@ -4667,5 +4672,5 @@ function getElementAnimateFn() {
4667
4672
  * Generated bundle index. Do not edit.
4668
4673
  */
4669
4674
 
4670
- export { AnimationDriver, Animation as ɵAnimation, AnimationEngine as ɵAnimationEngine, AnimationStyleNormalizer as ɵAnimationStyleNormalizer, CssKeyframesDriver as ɵCssKeyframesDriver, CssKeyframesPlayer as ɵCssKeyframesPlayer, NoopAnimationDriver as ɵNoopAnimationDriver, NoopAnimationStyleNormalizer as ɵNoopAnimationStyleNormalizer, WebAnimationsDriver as ɵWebAnimationsDriver, WebAnimationsPlayer as ɵWebAnimationsPlayer, WebAnimationsStyleNormalizer as ɵWebAnimationsStyleNormalizer, allowPreviousPlayerStylesMerge as ɵallowPreviousPlayerStylesMerge, containsElement as ɵcontainsElement, invokeQuery as ɵinvokeQuery, supportsWebAnimations as ɵsupportsWebAnimations, validateStyleProperty as ɵvalidateStyleProperty };
4675
+ 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 };
4671
4676
  //# sourceMappingURL=browser.mjs.map