UNPKG

277 kBJavaScriptView Raw
1/**
2 * @license Angular v9.0.1
3 * (c) 2010-2020 Google LLC. https://angular.io/
4 * License: MIT
5 */
6
7import { ɵAnimationGroupPlayer, NoopAnimationPlayer, AUTO_STYLE, ɵPRE_STYLE, sequence, style } from '@angular/animations';
8import { Injectable } from '@angular/core';
9
10/**
11 * @fileoverview added by tsickle
12 * Generated from: packages/animations/browser/src/render/shared.ts
13 * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
14 */
15/**
16 * @return {?}
17 */
18function isBrowser() {
19 return (typeof window !== 'undefined' && typeof window.document !== 'undefined');
20}
21/**
22 * @return {?}
23 */
24function isNode() {
25 return (typeof process !== 'undefined');
26}
27/**
28 * @param {?} players
29 * @return {?}
30 */
31function optimizeGroupPlayer(players) {
32 switch (players.length) {
33 case 0:
34 return new NoopAnimationPlayer();
35 case 1:
36 return players[0];
37 default:
38 return new ɵAnimationGroupPlayer(players);
39 }
40}
41/**
42 * @param {?} driver
43 * @param {?} normalizer
44 * @param {?} element
45 * @param {?} keyframes
46 * @param {?=} preStyles
47 * @param {?=} postStyles
48 * @return {?}
49 */
50function normalizeKeyframes(driver, normalizer, element, keyframes, preStyles = {}, postStyles = {}) {
51 /** @type {?} */
52 const errors = [];
53 /** @type {?} */
54 const normalizedKeyframes = [];
55 /** @type {?} */
56 let previousOffset = -1;
57 /** @type {?} */
58 let previousKeyframe = null;
59 keyframes.forEach((/**
60 * @param {?} kf
61 * @return {?}
62 */
63 kf => {
64 /** @type {?} */
65 const offset = (/** @type {?} */ (kf['offset']));
66 /** @type {?} */
67 const isSameOffset = offset == previousOffset;
68 /** @type {?} */
69 const normalizedKeyframe = (isSameOffset && previousKeyframe) || {};
70 Object.keys(kf).forEach((/**
71 * @param {?} prop
72 * @return {?}
73 */
74 prop => {
75 /** @type {?} */
76 let normalizedProp = prop;
77 /** @type {?} */
78 let normalizedValue = kf[prop];
79 if (prop !== 'offset') {
80 normalizedProp = normalizer.normalizePropertyName(normalizedProp, errors);
81 switch (normalizedValue) {
82 case ɵPRE_STYLE:
83 normalizedValue = preStyles[prop];
84 break;
85 case AUTO_STYLE:
86 normalizedValue = postStyles[prop];
87 break;
88 default:
89 normalizedValue =
90 normalizer.normalizeStyleValue(prop, normalizedProp, normalizedValue, errors);
91 break;
92 }
93 }
94 normalizedKeyframe[normalizedProp] = normalizedValue;
95 }));
96 if (!isSameOffset) {
97 normalizedKeyframes.push(normalizedKeyframe);
98 }
99 previousKeyframe = normalizedKeyframe;
100 previousOffset = offset;
101 }));
102 if (errors.length) {
103 /** @type {?} */
104 const LINE_START = '\n - ';
105 throw new Error(`Unable to animate due to the following errors:${LINE_START}${errors.join(LINE_START)}`);
106 }
107 return normalizedKeyframes;
108}
109/**
110 * @param {?} player
111 * @param {?} eventName
112 * @param {?} event
113 * @param {?} callback
114 * @return {?}
115 */
116function listenOnPlayer(player, eventName, event, callback) {
117 switch (eventName) {
118 case 'start':
119 player.onStart((/**
120 * @return {?}
121 */
122 () => callback(event && copyAnimationEvent(event, 'start', player))));
123 break;
124 case 'done':
125 player.onDone((/**
126 * @return {?}
127 */
128 () => callback(event && copyAnimationEvent(event, 'done', player))));
129 break;
130 case 'destroy':
131 player.onDestroy((/**
132 * @return {?}
133 */
134 () => callback(event && copyAnimationEvent(event, 'destroy', player))));
135 break;
136 }
137}
138/**
139 * @param {?} e
140 * @param {?} phaseName
141 * @param {?} player
142 * @return {?}
143 */
144function copyAnimationEvent(e, phaseName, player) {
145 /** @type {?} */
146 const totalTime = player.totalTime;
147 /** @type {?} */
148 const disabled = ((/** @type {?} */ (player))).disabled ? true : false;
149 /** @type {?} */
150 const event = makeAnimationEvent(e.element, e.triggerName, e.fromState, e.toState, phaseName || e.phaseName, totalTime == undefined ? e.totalTime : totalTime, disabled);
151 /** @type {?} */
152 const data = ((/** @type {?} */ (e)))['_data'];
153 if (data != null) {
154 ((/** @type {?} */ (event)))['_data'] = data;
155 }
156 return event;
157}
158/**
159 * @param {?} element
160 * @param {?} triggerName
161 * @param {?} fromState
162 * @param {?} toState
163 * @param {?=} phaseName
164 * @param {?=} totalTime
165 * @param {?=} disabled
166 * @return {?}
167 */
168function makeAnimationEvent(element, triggerName, fromState, toState, phaseName = '', totalTime = 0, disabled) {
169 return { element, triggerName, fromState, toState, phaseName, totalTime, disabled: !!disabled };
170}
171/**
172 * @param {?} map
173 * @param {?} key
174 * @param {?} defaultValue
175 * @return {?}
176 */
177function getOrSetAsInMap(map, key, defaultValue) {
178 /** @type {?} */
179 let value;
180 if (map instanceof Map) {
181 value = map.get(key);
182 if (!value) {
183 map.set(key, value = defaultValue);
184 }
185 }
186 else {
187 value = map[key];
188 if (!value) {
189 value = map[key] = defaultValue;
190 }
191 }
192 return value;
193}
194/**
195 * @param {?} command
196 * @return {?}
197 */
198function parseTimelineCommand(command) {
199 /** @type {?} */
200 const separatorPos = command.indexOf(':');
201 /** @type {?} */
202 const id = command.substring(1, separatorPos);
203 /** @type {?} */
204 const action = command.substr(separatorPos + 1);
205 return [id, action];
206}
207/** @type {?} */
208let _contains = (/**
209 * @param {?} elm1
210 * @param {?} elm2
211 * @return {?}
212 */
213(elm1, elm2) => false);
214const ɵ0 = _contains;
215/** @type {?} */
216let _matches = (/**
217 * @param {?} element
218 * @param {?} selector
219 * @return {?}
220 */
221(element, selector) => false);
222const ɵ1 = _matches;
223/** @type {?} */
224let _query = (/**
225 * @param {?} element
226 * @param {?} selector
227 * @param {?} multi
228 * @return {?}
229 */
230(element, selector, multi) => {
231 return [];
232});
233const ɵ2 = _query;
234// Define utility methods for browsers and platform-server(domino) where Element
235// and utility methods exist.
236/** @type {?} */
237const _isNode = isNode();
238if (_isNode || typeof Element !== 'undefined') {
239 // this is well supported in all browsers
240 _contains = (/**
241 * @param {?} elm1
242 * @param {?} elm2
243 * @return {?}
244 */
245 (elm1, elm2) => { return (/** @type {?} */ (elm1.contains(elm2))); });
246 _matches = ((/**
247 * @return {?}
248 */
249 () => {
250 if (_isNode || Element.prototype.matches) {
251 return (/**
252 * @param {?} element
253 * @param {?} selector
254 * @return {?}
255 */
256 (element, selector) => element.matches(selector));
257 }
258 else {
259 /** @type {?} */
260 const proto = (/** @type {?} */ (Element.prototype));
261 /** @type {?} */
262 const fn = proto.matchesSelector || proto.mozMatchesSelector || proto.msMatchesSelector ||
263 proto.oMatchesSelector || proto.webkitMatchesSelector;
264 if (fn) {
265 return (/**
266 * @param {?} element
267 * @param {?} selector
268 * @return {?}
269 */
270 (element, selector) => fn.apply(element, [selector]));
271 }
272 else {
273 return _matches;
274 }
275 }
276 }))();
277 _query = (/**
278 * @param {?} element
279 * @param {?} selector
280 * @param {?} multi
281 * @return {?}
282 */
283 (element, selector, multi) => {
284 /** @type {?} */
285 let results = [];
286 if (multi) {
287 results.push(...element.querySelectorAll(selector));
288 }
289 else {
290 /** @type {?} */
291 const elm = element.querySelector(selector);
292 if (elm) {
293 results.push(elm);
294 }
295 }
296 return results;
297 });
298}
299/**
300 * @param {?} prop
301 * @return {?}
302 */
303function containsVendorPrefix(prop) {
304 // Webkit is the only real popular vendor prefix nowadays
305 // cc: http://shouldiprefix.com/
306 return prop.substring(1, 6) == 'ebkit'; // webkit or Webkit
307}
308/** @type {?} */
309let _CACHED_BODY = null;
310/** @type {?} */
311let _IS_WEBKIT = false;
312/**
313 * @param {?} prop
314 * @return {?}
315 */
316function validateStyleProperty(prop) {
317 if (!_CACHED_BODY) {
318 _CACHED_BODY = getBodyNode() || {};
319 _IS_WEBKIT = (/** @type {?} */ (_CACHED_BODY)).style ? ('WebkitAppearance' in (/** @type {?} */ (_CACHED_BODY)).style) : false;
320 }
321 /** @type {?} */
322 let result = true;
323 if ((/** @type {?} */ (_CACHED_BODY)).style && !containsVendorPrefix(prop)) {
324 result = prop in (/** @type {?} */ (_CACHED_BODY)).style;
325 if (!result && _IS_WEBKIT) {
326 /** @type {?} */
327 const camelProp = 'Webkit' + prop.charAt(0).toUpperCase() + prop.substr(1);
328 result = camelProp in (/** @type {?} */ (_CACHED_BODY)).style;
329 }
330 }
331 return result;
332}
333/**
334 * @return {?}
335 */
336function getBodyNode() {
337 if (typeof document != 'undefined') {
338 return document.body;
339 }
340 return null;
341}
342/** @type {?} */
343const matchesElement = _matches;
344/** @type {?} */
345const containsElement = _contains;
346/** @type {?} */
347const invokeQuery = _query;
348/**
349 * @param {?} object
350 * @return {?}
351 */
352function hypenatePropsObject(object) {
353 /** @type {?} */
354 const newObj = {};
355 Object.keys(object).forEach((/**
356 * @param {?} prop
357 * @return {?}
358 */
359 prop => {
360 /** @type {?} */
361 const newProp = prop.replace(/([a-z])([A-Z])/g, '$1-$2');
362 newObj[newProp] = object[prop];
363 }));
364 return newObj;
365}
366
367/**
368 * @fileoverview added by tsickle
369 * Generated from: packages/animations/browser/src/render/animation_driver.ts
370 * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
371 */
372/**
373 * \@publicApi
374 */
375class NoopAnimationDriver {
376 /**
377 * @param {?} prop
378 * @return {?}
379 */
380 validateStyleProperty(prop) { return validateStyleProperty(prop); }
381 /**
382 * @param {?} element
383 * @param {?} selector
384 * @return {?}
385 */
386 matchesElement(element, selector) {
387 return matchesElement(element, selector);
388 }
389 /**
390 * @param {?} elm1
391 * @param {?} elm2
392 * @return {?}
393 */
394 containsElement(elm1, elm2) { return containsElement(elm1, elm2); }
395 /**
396 * @param {?} element
397 * @param {?} selector
398 * @param {?} multi
399 * @return {?}
400 */
401 query(element, selector, multi) {
402 return invokeQuery(element, selector, multi);
403 }
404 /**
405 * @param {?} element
406 * @param {?} prop
407 * @param {?=} defaultValue
408 * @return {?}
409 */
410 computeStyle(element, prop, defaultValue) {
411 return defaultValue || '';
412 }
413 /**
414 * @param {?} element
415 * @param {?} keyframes
416 * @param {?} duration
417 * @param {?} delay
418 * @param {?} easing
419 * @param {?=} previousPlayers
420 * @param {?=} scrubberAccessRequested
421 * @return {?}
422 */
423 animate(element, keyframes, duration, delay, easing, previousPlayers = [], scrubberAccessRequested) {
424 return new NoopAnimationPlayer(duration, delay);
425 }
426}
427NoopAnimationDriver.decorators = [
428 { type: Injectable }
429];
430/**
431 * \@publicApi
432 * @abstract
433 */
434class AnimationDriver {
435}
436AnimationDriver.NOOP = new NoopAnimationDriver();
437if (false) {
438 /** @type {?} */
439 AnimationDriver.NOOP;
440 /**
441 * @abstract
442 * @param {?} prop
443 * @return {?}
444 */
445 AnimationDriver.prototype.validateStyleProperty = function (prop) { };
446 /**
447 * @abstract
448 * @param {?} element
449 * @param {?} selector
450 * @return {?}
451 */
452 AnimationDriver.prototype.matchesElement = function (element, selector) { };
453 /**
454 * @abstract
455 * @param {?} elm1
456 * @param {?} elm2
457 * @return {?}
458 */
459 AnimationDriver.prototype.containsElement = function (elm1, elm2) { };
460 /**
461 * @abstract
462 * @param {?} element
463 * @param {?} selector
464 * @param {?} multi
465 * @return {?}
466 */
467 AnimationDriver.prototype.query = function (element, selector, multi) { };
468 /**
469 * @abstract
470 * @param {?} element
471 * @param {?} prop
472 * @param {?=} defaultValue
473 * @return {?}
474 */
475 AnimationDriver.prototype.computeStyle = function (element, prop, defaultValue) { };
476 /**
477 * @abstract
478 * @param {?} element
479 * @param {?} keyframes
480 * @param {?} duration
481 * @param {?} delay
482 * @param {?=} easing
483 * @param {?=} previousPlayers
484 * @param {?=} scrubberAccessRequested
485 * @return {?}
486 */
487 AnimationDriver.prototype.animate = function (element, keyframes, duration, delay, easing, previousPlayers, scrubberAccessRequested) { };
488}
489
490/**
491 * @fileoverview added by tsickle
492 * Generated from: packages/animations/browser/src/util.ts
493 * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
494 */
495/** @type {?} */
496const ONE_SECOND = 1000;
497/** @type {?} */
498const SUBSTITUTION_EXPR_START = '{{';
499/** @type {?} */
500const SUBSTITUTION_EXPR_END = '}}';
501/** @type {?} */
502const ENTER_CLASSNAME = 'ng-enter';
503/** @type {?} */
504const LEAVE_CLASSNAME = 'ng-leave';
505/** @type {?} */
506const ENTER_SELECTOR = '.ng-enter';
507/** @type {?} */
508const LEAVE_SELECTOR = '.ng-leave';
509/** @type {?} */
510const NG_TRIGGER_CLASSNAME = 'ng-trigger';
511/** @type {?} */
512const NG_TRIGGER_SELECTOR = '.ng-trigger';
513/** @type {?} */
514const NG_ANIMATING_CLASSNAME = 'ng-animating';
515/** @type {?} */
516const NG_ANIMATING_SELECTOR = '.ng-animating';
517/**
518 * @param {?} value
519 * @return {?}
520 */
521function resolveTimingValue(value) {
522 if (typeof value == 'number')
523 return value;
524 /** @type {?} */
525 const matches = value.match(/^(-?[\.\d]+)(m?s)/);
526 if (!matches || matches.length < 2)
527 return 0;
528 return _convertTimeValueToMS(parseFloat(matches[1]), matches[2]);
529}
530/**
531 * @param {?} value
532 * @param {?} unit
533 * @return {?}
534 */
535function _convertTimeValueToMS(value, unit) {
536 switch (unit) {
537 case 's':
538 return value * ONE_SECOND;
539 default: // ms or something else
540 return value;
541 }
542}
543/**
544 * @param {?} timings
545 * @param {?} errors
546 * @param {?=} allowNegativeValues
547 * @return {?}
548 */
549function resolveTiming(timings, errors, allowNegativeValues) {
550 return timings.hasOwnProperty('duration') ?
551 (/** @type {?} */ (timings)) :
552 parseTimeExpression((/** @type {?} */ (timings)), errors, allowNegativeValues);
553}
554/**
555 * @param {?} exp
556 * @param {?} errors
557 * @param {?=} allowNegativeValues
558 * @return {?}
559 */
560function parseTimeExpression(exp, errors, allowNegativeValues) {
561 /** @type {?} */
562 const regex = /^(-?[\.\d]+)(m?s)(?:\s+(-?[\.\d]+)(m?s))?(?:\s+([-a-z]+(?:\(.+?\))?))?$/i;
563 /** @type {?} */
564 let duration;
565 /** @type {?} */
566 let delay = 0;
567 /** @type {?} */
568 let easing = '';
569 if (typeof exp === 'string') {
570 /** @type {?} */
571 const matches = exp.match(regex);
572 if (matches === null) {
573 errors.push(`The provided timing value "${exp}" is invalid.`);
574 return { duration: 0, delay: 0, easing: '' };
575 }
576 duration = _convertTimeValueToMS(parseFloat(matches[1]), matches[2]);
577 /** @type {?} */
578 const delayMatch = matches[3];
579 if (delayMatch != null) {
580 delay = _convertTimeValueToMS(parseFloat(delayMatch), matches[4]);
581 }
582 /** @type {?} */
583 const easingVal = matches[5];
584 if (easingVal) {
585 easing = easingVal;
586 }
587 }
588 else {
589 duration = exp;
590 }
591 if (!allowNegativeValues) {
592 /** @type {?} */
593 let containsErrors = false;
594 /** @type {?} */
595 let startIndex = errors.length;
596 if (duration < 0) {
597 errors.push(`Duration values below 0 are not allowed for this animation step.`);
598 containsErrors = true;
599 }
600 if (delay < 0) {
601 errors.push(`Delay values below 0 are not allowed for this animation step.`);
602 containsErrors = true;
603 }
604 if (containsErrors) {
605 errors.splice(startIndex, 0, `The provided timing value "${exp}" is invalid.`);
606 }
607 }
608 return { duration, delay, easing };
609}
610/**
611 * @param {?} obj
612 * @param {?=} destination
613 * @return {?}
614 */
615function copyObj(obj, destination = {}) {
616 Object.keys(obj).forEach((/**
617 * @param {?} prop
618 * @return {?}
619 */
620 prop => { destination[prop] = obj[prop]; }));
621 return destination;
622}
623/**
624 * @param {?} styles
625 * @return {?}
626 */
627function normalizeStyles(styles) {
628 /** @type {?} */
629 const normalizedStyles = {};
630 if (Array.isArray(styles)) {
631 styles.forEach((/**
632 * @param {?} data
633 * @return {?}
634 */
635 data => copyStyles(data, false, normalizedStyles)));
636 }
637 else {
638 copyStyles(styles, false, normalizedStyles);
639 }
640 return normalizedStyles;
641}
642/**
643 * @param {?} styles
644 * @param {?} readPrototype
645 * @param {?=} destination
646 * @return {?}
647 */
648function copyStyles(styles, readPrototype, destination = {}) {
649 if (readPrototype) {
650 // we make use of a for-in loop so that the
651 // prototypically inherited properties are
652 // revealed from the backFill map
653 for (let prop in styles) {
654 destination[prop] = styles[prop];
655 }
656 }
657 else {
658 copyObj(styles, destination);
659 }
660 return destination;
661}
662/**
663 * @param {?} element
664 * @param {?} key
665 * @param {?} value
666 * @return {?}
667 */
668function getStyleAttributeString(element, key, value) {
669 // Return the key-value pair string to be added to the style attribute for the
670 // given CSS style key.
671 if (value) {
672 return key + ':' + value + ';';
673 }
674 else {
675 return '';
676 }
677}
678/**
679 * @param {?} element
680 * @return {?}
681 */
682function writeStyleAttribute(element) {
683 // Read the style property of the element and manually reflect it to the
684 // style attribute. This is needed because Domino on platform-server doesn't
685 // understand the full set of allowed CSS properties and doesn't reflect some
686 // of them automatically.
687 /** @type {?} */
688 let styleAttrValue = '';
689 for (let i = 0; i < element.style.length; i++) {
690 /** @type {?} */
691 const key = element.style.item(i);
692 styleAttrValue += getStyleAttributeString(element, key, element.style.getPropertyValue(key));
693 }
694 for (const key in element.style) {
695 // Skip internal Domino properties that don't need to be reflected.
696 if (!element.style.hasOwnProperty(key) || key.startsWith('_')) {
697 continue;
698 }
699 /** @type {?} */
700 const dashKey = camelCaseToDashCase(key);
701 styleAttrValue += getStyleAttributeString(element, dashKey, element.style[key]);
702 }
703 element.setAttribute('style', styleAttrValue);
704}
705/**
706 * @param {?} element
707 * @param {?} styles
708 * @param {?=} formerStyles
709 * @return {?}
710 */
711function setStyles(element, styles, formerStyles) {
712 if (element['style']) {
713 Object.keys(styles).forEach((/**
714 * @param {?} prop
715 * @return {?}
716 */
717 prop => {
718 /** @type {?} */
719 const camelProp = dashCaseToCamelCase(prop);
720 if (formerStyles && !formerStyles.hasOwnProperty(prop)) {
721 formerStyles[prop] = element.style[camelProp];
722 }
723 element.style[camelProp] = styles[prop];
724 }));
725 // On the server set the 'style' attribute since it's not automatically reflected.
726 if (isNode()) {
727 writeStyleAttribute(element);
728 }
729 }
730}
731/**
732 * @param {?} element
733 * @param {?} styles
734 * @return {?}
735 */
736function eraseStyles(element, styles) {
737 if (element['style']) {
738 Object.keys(styles).forEach((/**
739 * @param {?} prop
740 * @return {?}
741 */
742 prop => {
743 /** @type {?} */
744 const camelProp = dashCaseToCamelCase(prop);
745 element.style[camelProp] = '';
746 }));
747 // On the server set the 'style' attribute since it's not automatically reflected.
748 if (isNode()) {
749 writeStyleAttribute(element);
750 }
751 }
752}
753/**
754 * @param {?} steps
755 * @return {?}
756 */
757function normalizeAnimationEntry(steps) {
758 if (Array.isArray(steps)) {
759 if (steps.length == 1)
760 return steps[0];
761 return sequence(steps);
762 }
763 return (/** @type {?} */ (steps));
764}
765/**
766 * @param {?} value
767 * @param {?} options
768 * @param {?} errors
769 * @return {?}
770 */
771function validateStyleParams(value, options, errors) {
772 /** @type {?} */
773 const params = options.params || {};
774 /** @type {?} */
775 const matches = extractStyleParams(value);
776 if (matches.length) {
777 matches.forEach((/**
778 * @param {?} varName
779 * @return {?}
780 */
781 varName => {
782 if (!params.hasOwnProperty(varName)) {
783 errors.push(`Unable to resolve the local animation param ${varName} in the given list of values`);
784 }
785 }));
786 }
787}
788/** @type {?} */
789const PARAM_REGEX = new RegExp(`${SUBSTITUTION_EXPR_START}\\s*(.+?)\\s*${SUBSTITUTION_EXPR_END}`, 'g');
790/**
791 * @param {?} value
792 * @return {?}
793 */
794function extractStyleParams(value) {
795 /** @type {?} */
796 let params = [];
797 if (typeof value === 'string') {
798 /** @type {?} */
799 let match;
800 while (match = PARAM_REGEX.exec(value)) {
801 params.push((/** @type {?} */ (match[1])));
802 }
803 PARAM_REGEX.lastIndex = 0;
804 }
805 return params;
806}
807/**
808 * @param {?} value
809 * @param {?} params
810 * @param {?} errors
811 * @return {?}
812 */
813function interpolateParams(value, params, errors) {
814 /** @type {?} */
815 const original = value.toString();
816 /** @type {?} */
817 const str = original.replace(PARAM_REGEX, (/**
818 * @param {?} _
819 * @param {?} varName
820 * @return {?}
821 */
822 (_, varName) => {
823 /** @type {?} */
824 let localVal = params[varName];
825 // this means that the value was never overridden by the data passed in by the user
826 if (!params.hasOwnProperty(varName)) {
827 errors.push(`Please provide a value for the animation param ${varName}`);
828 localVal = '';
829 }
830 return localVal.toString();
831 }));
832 // we do this to assert that numeric values stay as they are
833 return str == original ? value : str;
834}
835/**
836 * @param {?} iterator
837 * @return {?}
838 */
839function iteratorToArray(iterator) {
840 /** @type {?} */
841 const arr = [];
842 /** @type {?} */
843 let item = iterator.next();
844 while (!item.done) {
845 arr.push(item.value);
846 item = iterator.next();
847 }
848 return arr;
849}
850/**
851 * @param {?} source
852 * @param {?} destination
853 * @return {?}
854 */
855function mergeAnimationOptions(source, destination) {
856 if (source.params) {
857 /** @type {?} */
858 const p0 = source.params;
859 if (!destination.params) {
860 destination.params = {};
861 }
862 /** @type {?} */
863 const p1 = destination.params;
864 Object.keys(p0).forEach((/**
865 * @param {?} param
866 * @return {?}
867 */
868 param => {
869 if (!p1.hasOwnProperty(param)) {
870 p1[param] = p0[param];
871 }
872 }));
873 }
874 return destination;
875}
876/** @type {?} */
877const DASH_CASE_REGEXP = /-+([a-z0-9])/g;
878/**
879 * @param {?} input
880 * @return {?}
881 */
882function dashCaseToCamelCase(input) {
883 return input.replace(DASH_CASE_REGEXP, (/**
884 * @param {...?} m
885 * @return {?}
886 */
887 (...m) => m[1].toUpperCase()));
888}
889/**
890 * @param {?} input
891 * @return {?}
892 */
893function camelCaseToDashCase(input) {
894 return input.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase();
895}
896/**
897 * @param {?} duration
898 * @param {?} delay
899 * @return {?}
900 */
901function allowPreviousPlayerStylesMerge(duration, delay) {
902 return duration === 0 || delay === 0;
903}
904/**
905 * @param {?} element
906 * @param {?} keyframes
907 * @param {?} previousStyles
908 * @return {?}
909 */
910function balancePreviousStylesIntoKeyframes(element, keyframes, previousStyles) {
911 /** @type {?} */
912 const previousStyleProps = Object.keys(previousStyles);
913 if (previousStyleProps.length && keyframes.length) {
914 /** @type {?} */
915 let startingKeyframe = keyframes[0];
916 /** @type {?} */
917 let missingStyleProps = [];
918 previousStyleProps.forEach((/**
919 * @param {?} prop
920 * @return {?}
921 */
922 prop => {
923 if (!startingKeyframe.hasOwnProperty(prop)) {
924 missingStyleProps.push(prop);
925 }
926 startingKeyframe[prop] = previousStyles[prop];
927 }));
928 if (missingStyleProps.length) {
929 // tslint:disable-next-line
930 for (var i = 1; i < keyframes.length; i++) {
931 /** @type {?} */
932 let kf = keyframes[i];
933 missingStyleProps.forEach((/**
934 * @param {?} prop
935 * @return {?}
936 */
937 function (prop) { kf[prop] = computeStyle(element, prop); }));
938 }
939 }
940 }
941 return keyframes;
942}
943/**
944 * @param {?} visitor
945 * @param {?} node
946 * @param {?} context
947 * @return {?}
948 */
949function visitDslNode(visitor, node, context) {
950 switch (node.type) {
951 case 7 /* Trigger */:
952 return visitor.visitTrigger(node, context);
953 case 0 /* State */:
954 return visitor.visitState(node, context);
955 case 1 /* Transition */:
956 return visitor.visitTransition(node, context);
957 case 2 /* Sequence */:
958 return visitor.visitSequence(node, context);
959 case 3 /* Group */:
960 return visitor.visitGroup(node, context);
961 case 4 /* Animate */:
962 return visitor.visitAnimate(node, context);
963 case 5 /* Keyframes */:
964 return visitor.visitKeyframes(node, context);
965 case 6 /* Style */:
966 return visitor.visitStyle(node, context);
967 case 8 /* Reference */:
968 return visitor.visitReference(node, context);
969 case 9 /* AnimateChild */:
970 return visitor.visitAnimateChild(node, context);
971 case 10 /* AnimateRef */:
972 return visitor.visitAnimateRef(node, context);
973 case 11 /* Query */:
974 return visitor.visitQuery(node, context);
975 case 12 /* Stagger */:
976 return visitor.visitStagger(node, context);
977 default:
978 throw new Error(`Unable to resolve animation metadata node #${node.type}`);
979 }
980}
981/**
982 * @param {?} element
983 * @param {?} prop
984 * @return {?}
985 */
986function computeStyle(element, prop) {
987 return ((/** @type {?} */ (window.getComputedStyle(element))))[prop];
988}
989
990/**
991 * @fileoverview added by tsickle
992 * Generated from: packages/animations/browser/src/dsl/animation_transition_expr.ts
993 * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
994 */
995/**
996 * @license
997 * Copyright Google Inc. All Rights Reserved.
998 *
999 * Use of this source code is governed by an MIT-style license that can be
1000 * found in the LICENSE file at https://angular.io/license
1001 * @type {?}
1002 */
1003const ANY_STATE = '*';
1004/**
1005 * @param {?} transitionValue
1006 * @param {?} errors
1007 * @return {?}
1008 */
1009function parseTransitionExpr(transitionValue, errors) {
1010 /** @type {?} */
1011 const expressions = [];
1012 if (typeof transitionValue == 'string') {
1013 transitionValue.split(/\s*,\s*/).forEach((/**
1014 * @param {?} str
1015 * @return {?}
1016 */
1017 str => parseInnerTransitionStr(str, expressions, errors)));
1018 }
1019 else {
1020 expressions.push((/** @type {?} */ (transitionValue)));
1021 }
1022 return expressions;
1023}
1024/**
1025 * @param {?} eventStr
1026 * @param {?} expressions
1027 * @param {?} errors
1028 * @return {?}
1029 */
1030function parseInnerTransitionStr(eventStr, expressions, errors) {
1031 if (eventStr[0] == ':') {
1032 /** @type {?} */
1033 const result = parseAnimationAlias(eventStr, errors);
1034 if (typeof result == 'function') {
1035 expressions.push(result);
1036 return;
1037 }
1038 eventStr = result;
1039 }
1040 /** @type {?} */
1041 const match = eventStr.match(/^(\*|[-\w]+)\s*(<?[=-]>)\s*(\*|[-\w]+)$/);
1042 if (match == null || match.length < 4) {
1043 errors.push(`The provided transition expression "${eventStr}" is not supported`);
1044 return expressions;
1045 }
1046 /** @type {?} */
1047 const fromState = match[1];
1048 /** @type {?} */
1049 const separator = match[2];
1050 /** @type {?} */
1051 const toState = match[3];
1052 expressions.push(makeLambdaFromStates(fromState, toState));
1053 /** @type {?} */
1054 const isFullAnyStateExpr = fromState == ANY_STATE && toState == ANY_STATE;
1055 if (separator[0] == '<' && !isFullAnyStateExpr) {
1056 expressions.push(makeLambdaFromStates(toState, fromState));
1057 }
1058}
1059/**
1060 * @param {?} alias
1061 * @param {?} errors
1062 * @return {?}
1063 */
1064function parseAnimationAlias(alias, errors) {
1065 switch (alias) {
1066 case ':enter':
1067 return 'void => *';
1068 case ':leave':
1069 return '* => void';
1070 case ':increment':
1071 return (/**
1072 * @param {?} fromState
1073 * @param {?} toState
1074 * @return {?}
1075 */
1076 (fromState, toState) => parseFloat(toState) > parseFloat(fromState));
1077 case ':decrement':
1078 return (/**
1079 * @param {?} fromState
1080 * @param {?} toState
1081 * @return {?}
1082 */
1083 (fromState, toState) => parseFloat(toState) < parseFloat(fromState));
1084 default:
1085 errors.push(`The transition alias value "${alias}" is not supported`);
1086 return '* => *';
1087 }
1088}
1089// DO NOT REFACTOR ... keep the follow set instantiations
1090// with the values intact (closure compiler for some reason
1091// removes follow-up lines that add the values outside of
1092// the constructor...
1093/** @type {?} */
1094const TRUE_BOOLEAN_VALUES = new Set(['true', '1']);
1095/** @type {?} */
1096const FALSE_BOOLEAN_VALUES = new Set(['false', '0']);
1097/**
1098 * @param {?} lhs
1099 * @param {?} rhs
1100 * @return {?}
1101 */
1102function makeLambdaFromStates(lhs, rhs) {
1103 /** @type {?} */
1104 const LHS_MATCH_BOOLEAN = TRUE_BOOLEAN_VALUES.has(lhs) || FALSE_BOOLEAN_VALUES.has(lhs);
1105 /** @type {?} */
1106 const RHS_MATCH_BOOLEAN = TRUE_BOOLEAN_VALUES.has(rhs) || FALSE_BOOLEAN_VALUES.has(rhs);
1107 return (/**
1108 * @param {?} fromState
1109 * @param {?} toState
1110 * @return {?}
1111 */
1112 (fromState, toState) => {
1113 /** @type {?} */
1114 let lhsMatch = lhs == ANY_STATE || lhs == fromState;
1115 /** @type {?} */
1116 let rhsMatch = rhs == ANY_STATE || rhs == toState;
1117 if (!lhsMatch && LHS_MATCH_BOOLEAN && typeof fromState === 'boolean') {
1118 lhsMatch = fromState ? TRUE_BOOLEAN_VALUES.has(lhs) : FALSE_BOOLEAN_VALUES.has(lhs);
1119 }
1120 if (!rhsMatch && RHS_MATCH_BOOLEAN && typeof toState === 'boolean') {
1121 rhsMatch = toState ? TRUE_BOOLEAN_VALUES.has(rhs) : FALSE_BOOLEAN_VALUES.has(rhs);
1122 }
1123 return lhsMatch && rhsMatch;
1124 });
1125}
1126
1127/**
1128 * @fileoverview added by tsickle
1129 * Generated from: packages/animations/browser/src/dsl/animation_ast_builder.ts
1130 * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
1131 */
1132/** @type {?} */
1133const SELF_TOKEN = ':self';
1134/** @type {?} */
1135const SELF_TOKEN_REGEX = new RegExp(`\s*${SELF_TOKEN}\s*,?`, 'g');
1136/*
1137 * [Validation]
1138 * The visitor code below will traverse the animation AST generated by the animation verb functions
1139 * (the output is a tree of objects) and attempt to perform a series of validations on the data. The
1140 * following corner-cases will be validated:
1141 *
1142 * 1. Overlap of animations
1143 * Given that a CSS property cannot be animated in more than one place at the same time, it's
1144 * important that this behavior is detected and validated. The way in which this occurs is that
1145 * each time a style property is examined, a string-map containing the property will be updated with
1146 * the start and end times for when the property is used within an animation step.
1147 *
1148 * If there are two or more parallel animations that are currently running (these are invoked by the
1149 * group()) on the same element then the validator will throw an error. Since the start/end timing
1150 * values are collected for each property then if the current animation step is animating the same
1151 * property and its timing values fall anywhere into the window of time that the property is
1152 * currently being animated within then this is what causes an error.
1153 *
1154 * 2. Timing values
1155 * The validator will validate to see if a timing value of `duration delay easing` or
1156 * `durationNumber` is valid or not.
1157 *
1158 * (note that upon validation the code below will replace the timing data with an object containing
1159 * {duration,delay,easing}.
1160 *
1161 * 3. Offset Validation
1162 * Each of the style() calls are allowed to have an offset value when placed inside of keyframes().
1163 * Offsets within keyframes() are considered valid when:
1164 *
1165 * - No offsets are used at all
1166 * - Each style() entry contains an offset value
1167 * - Each offset is between 0 and 1
1168 * - Each offset is greater to or equal than the previous one
1169 *
1170 * Otherwise an error will be thrown.
1171 */
1172/**
1173 * @param {?} driver
1174 * @param {?} metadata
1175 * @param {?} errors
1176 * @return {?}
1177 */
1178function buildAnimationAst(driver, metadata, errors) {
1179 return new AnimationAstBuilderVisitor(driver).build(metadata, errors);
1180}
1181/** @type {?} */
1182const ROOT_SELECTOR = '';
1183class AnimationAstBuilderVisitor {
1184 /**
1185 * @param {?} _driver
1186 */
1187 constructor(_driver) {
1188 this._driver = _driver;
1189 }
1190 /**
1191 * @param {?} metadata
1192 * @param {?} errors
1193 * @return {?}
1194 */
1195 build(metadata, errors) {
1196 /** @type {?} */
1197 const context = new AnimationAstBuilderContext(errors);
1198 this._resetContextStyleTimingState(context);
1199 return (/** @type {?} */ (visitDslNode(this, normalizeAnimationEntry(metadata), context)));
1200 }
1201 /**
1202 * @private
1203 * @param {?} context
1204 * @return {?}
1205 */
1206 _resetContextStyleTimingState(context) {
1207 context.currentQuerySelector = ROOT_SELECTOR;
1208 context.collectedStyles = {};
1209 context.collectedStyles[ROOT_SELECTOR] = {};
1210 context.currentTime = 0;
1211 }
1212 /**
1213 * @param {?} metadata
1214 * @param {?} context
1215 * @return {?}
1216 */
1217 visitTrigger(metadata, context) {
1218 /** @type {?} */
1219 let queryCount = context.queryCount = 0;
1220 /** @type {?} */
1221 let depCount = context.depCount = 0;
1222 /** @type {?} */
1223 const states = [];
1224 /** @type {?} */
1225 const transitions = [];
1226 if (metadata.name.charAt(0) == '@') {
1227 context.errors.push('animation triggers cannot be prefixed with an `@` sign (e.g. trigger(\'@foo\', [...]))');
1228 }
1229 metadata.definitions.forEach((/**
1230 * @param {?} def
1231 * @return {?}
1232 */
1233 def => {
1234 this._resetContextStyleTimingState(context);
1235 if (def.type == 0 /* State */) {
1236 /** @type {?} */
1237 const stateDef = (/** @type {?} */ (def));
1238 /** @type {?} */
1239 const name = stateDef.name;
1240 name.toString().split(/\s*,\s*/).forEach((/**
1241 * @param {?} n
1242 * @return {?}
1243 */
1244 n => {
1245 stateDef.name = n;
1246 states.push(this.visitState(stateDef, context));
1247 }));
1248 stateDef.name = name;
1249 }
1250 else if (def.type == 1 /* Transition */) {
1251 /** @type {?} */
1252 const transition = this.visitTransition((/** @type {?} */ (def)), context);
1253 queryCount += transition.queryCount;
1254 depCount += transition.depCount;
1255 transitions.push(transition);
1256 }
1257 else {
1258 context.errors.push('only state() and transition() definitions can sit inside of a trigger()');
1259 }
1260 }));
1261 return {
1262 type: 7 /* Trigger */,
1263 name: metadata.name, states, transitions, queryCount, depCount,
1264 options: null
1265 };
1266 }
1267 /**
1268 * @param {?} metadata
1269 * @param {?} context
1270 * @return {?}
1271 */
1272 visitState(metadata, context) {
1273 /** @type {?} */
1274 const styleAst = this.visitStyle(metadata.styles, context);
1275 /** @type {?} */
1276 const astParams = (metadata.options && metadata.options.params) || null;
1277 if (styleAst.containsDynamicStyles) {
1278 /** @type {?} */
1279 const missingSubs = new Set();
1280 /** @type {?} */
1281 const params = astParams || {};
1282 styleAst.styles.forEach((/**
1283 * @param {?} value
1284 * @return {?}
1285 */
1286 value => {
1287 if (isObject(value)) {
1288 /** @type {?} */
1289 const stylesObj = (/** @type {?} */ (value));
1290 Object.keys(stylesObj).forEach((/**
1291 * @param {?} prop
1292 * @return {?}
1293 */
1294 prop => {
1295 extractStyleParams(stylesObj[prop]).forEach((/**
1296 * @param {?} sub
1297 * @return {?}
1298 */
1299 sub => {
1300 if (!params.hasOwnProperty(sub)) {
1301 missingSubs.add(sub);
1302 }
1303 }));
1304 }));
1305 }
1306 }));
1307 if (missingSubs.size) {
1308 /** @type {?} */
1309 const missingSubsArr = iteratorToArray(missingSubs.values());
1310 context.errors.push(`state("${metadata.name}", ...) must define default values for all the following style substitutions: ${missingSubsArr.join(', ')}`);
1311 }
1312 }
1313 return {
1314 type: 0 /* State */,
1315 name: metadata.name,
1316 style: styleAst,
1317 options: astParams ? { params: astParams } : null
1318 };
1319 }
1320 /**
1321 * @param {?} metadata
1322 * @param {?} context
1323 * @return {?}
1324 */
1325 visitTransition(metadata, context) {
1326 context.queryCount = 0;
1327 context.depCount = 0;
1328 /** @type {?} */
1329 const animation = visitDslNode(this, normalizeAnimationEntry(metadata.animation), context);
1330 /** @type {?} */
1331 const matchers = parseTransitionExpr(metadata.expr, context.errors);
1332 return {
1333 type: 1 /* Transition */,
1334 matchers,
1335 animation,
1336 queryCount: context.queryCount,
1337 depCount: context.depCount,
1338 options: normalizeAnimationOptions(metadata.options)
1339 };
1340 }
1341 /**
1342 * @param {?} metadata
1343 * @param {?} context
1344 * @return {?}
1345 */
1346 visitSequence(metadata, context) {
1347 return {
1348 type: 2 /* Sequence */,
1349 steps: metadata.steps.map((/**
1350 * @param {?} s
1351 * @return {?}
1352 */
1353 s => visitDslNode(this, s, context))),
1354 options: normalizeAnimationOptions(metadata.options)
1355 };
1356 }
1357 /**
1358 * @param {?} metadata
1359 * @param {?} context
1360 * @return {?}
1361 */
1362 visitGroup(metadata, context) {
1363 /** @type {?} */
1364 const currentTime = context.currentTime;
1365 /** @type {?} */
1366 let furthestTime = 0;
1367 /** @type {?} */
1368 const steps = metadata.steps.map((/**
1369 * @param {?} step
1370 * @return {?}
1371 */
1372 step => {
1373 context.currentTime = currentTime;
1374 /** @type {?} */
1375 const innerAst = visitDslNode(this, step, context);
1376 furthestTime = Math.max(furthestTime, context.currentTime);
1377 return innerAst;
1378 }));
1379 context.currentTime = furthestTime;
1380 return {
1381 type: 3 /* Group */,
1382 steps,
1383 options: normalizeAnimationOptions(metadata.options)
1384 };
1385 }
1386 /**
1387 * @param {?} metadata
1388 * @param {?} context
1389 * @return {?}
1390 */
1391 visitAnimate(metadata, context) {
1392 /** @type {?} */
1393 const timingAst = constructTimingAst(metadata.timings, context.errors);
1394 context.currentAnimateTimings = timingAst;
1395 /** @type {?} */
1396 let styleAst;
1397 /** @type {?} */
1398 let styleMetadata = metadata.styles ? metadata.styles : style({});
1399 if (styleMetadata.type == 5 /* Keyframes */) {
1400 styleAst = this.visitKeyframes((/** @type {?} */ (styleMetadata)), context);
1401 }
1402 else {
1403 /** @type {?} */
1404 let styleMetadata = (/** @type {?} */ (metadata.styles));
1405 /** @type {?} */
1406 let isEmpty = false;
1407 if (!styleMetadata) {
1408 isEmpty = true;
1409 /** @type {?} */
1410 const newStyleData = {};
1411 if (timingAst.easing) {
1412 newStyleData['easing'] = timingAst.easing;
1413 }
1414 styleMetadata = style(newStyleData);
1415 }
1416 context.currentTime += timingAst.duration + timingAst.delay;
1417 /** @type {?} */
1418 const _styleAst = this.visitStyle(styleMetadata, context);
1419 _styleAst.isEmptyStep = isEmpty;
1420 styleAst = _styleAst;
1421 }
1422 context.currentAnimateTimings = null;
1423 return {
1424 type: 4 /* Animate */,
1425 timings: timingAst,
1426 style: styleAst,
1427 options: null
1428 };
1429 }
1430 /**
1431 * @param {?} metadata
1432 * @param {?} context
1433 * @return {?}
1434 */
1435 visitStyle(metadata, context) {
1436 /** @type {?} */
1437 const ast = this._makeStyleAst(metadata, context);
1438 this._validateStyleAst(ast, context);
1439 return ast;
1440 }
1441 /**
1442 * @private
1443 * @param {?} metadata
1444 * @param {?} context
1445 * @return {?}
1446 */
1447 _makeStyleAst(metadata, context) {
1448 /** @type {?} */
1449 const styles = [];
1450 if (Array.isArray(metadata.styles)) {
1451 ((/** @type {?} */ (metadata.styles))).forEach((/**
1452 * @param {?} styleTuple
1453 * @return {?}
1454 */
1455 styleTuple => {
1456 if (typeof styleTuple == 'string') {
1457 if (styleTuple == AUTO_STYLE) {
1458 styles.push(styleTuple);
1459 }
1460 else {
1461 context.errors.push(`The provided style string value ${styleTuple} is not allowed.`);
1462 }
1463 }
1464 else {
1465 styles.push(styleTuple);
1466 }
1467 }));
1468 }
1469 else {
1470 styles.push(metadata.styles);
1471 }
1472 /** @type {?} */
1473 let containsDynamicStyles = false;
1474 /** @type {?} */
1475 let collectedEasing = null;
1476 styles.forEach((/**
1477 * @param {?} styleData
1478 * @return {?}
1479 */
1480 styleData => {
1481 if (isObject(styleData)) {
1482 /** @type {?} */
1483 const styleMap = (/** @type {?} */ (styleData));
1484 /** @type {?} */
1485 const easing = styleMap['easing'];
1486 if (easing) {
1487 collectedEasing = (/** @type {?} */ (easing));
1488 delete styleMap['easing'];
1489 }
1490 if (!containsDynamicStyles) {
1491 for (let prop in styleMap) {
1492 /** @type {?} */
1493 const value = styleMap[prop];
1494 if (value.toString().indexOf(SUBSTITUTION_EXPR_START) >= 0) {
1495 containsDynamicStyles = true;
1496 break;
1497 }
1498 }
1499 }
1500 }
1501 }));
1502 return {
1503 type: 6 /* Style */,
1504 styles,
1505 easing: collectedEasing,
1506 offset: metadata.offset, containsDynamicStyles,
1507 options: null
1508 };
1509 }
1510 /**
1511 * @private
1512 * @param {?} ast
1513 * @param {?} context
1514 * @return {?}
1515 */
1516 _validateStyleAst(ast, context) {
1517 /** @type {?} */
1518 const timings = context.currentAnimateTimings;
1519 /** @type {?} */
1520 let endTime = context.currentTime;
1521 /** @type {?} */
1522 let startTime = context.currentTime;
1523 if (timings && startTime > 0) {
1524 startTime -= timings.duration + timings.delay;
1525 }
1526 ast.styles.forEach((/**
1527 * @param {?} tuple
1528 * @return {?}
1529 */
1530 tuple => {
1531 if (typeof tuple == 'string')
1532 return;
1533 Object.keys(tuple).forEach((/**
1534 * @param {?} prop
1535 * @return {?}
1536 */
1537 prop => {
1538 if (!this._driver.validateStyleProperty(prop)) {
1539 context.errors.push(`The provided animation property "${prop}" is not a supported CSS property for animations`);
1540 return;
1541 }
1542 /** @type {?} */
1543 const collectedStyles = context.collectedStyles[(/** @type {?} */ (context.currentQuerySelector))];
1544 /** @type {?} */
1545 const collectedEntry = collectedStyles[prop];
1546 /** @type {?} */
1547 let updateCollectedStyle = true;
1548 if (collectedEntry) {
1549 if (startTime != endTime && startTime >= collectedEntry.startTime &&
1550 endTime <= collectedEntry.endTime) {
1551 context.errors.push(`The CSS property "${prop}" that exists between the times of "${collectedEntry.startTime}ms" and "${collectedEntry.endTime}ms" is also being animated in a parallel animation between the times of "${startTime}ms" and "${endTime}ms"`);
1552 updateCollectedStyle = false;
1553 }
1554 // we always choose the smaller start time value since we
1555 // want to have a record of the entire animation window where
1556 // the style property is being animated in between
1557 startTime = collectedEntry.startTime;
1558 }
1559 if (updateCollectedStyle) {
1560 collectedStyles[prop] = { startTime, endTime };
1561 }
1562 if (context.options) {
1563 validateStyleParams(tuple[prop], context.options, context.errors);
1564 }
1565 }));
1566 }));
1567 }
1568 /**
1569 * @param {?} metadata
1570 * @param {?} context
1571 * @return {?}
1572 */
1573 visitKeyframes(metadata, context) {
1574 /** @type {?} */
1575 const ast = { type: 5 /* Keyframes */, styles: [], options: null };
1576 if (!context.currentAnimateTimings) {
1577 context.errors.push(`keyframes() must be placed inside of a call to animate()`);
1578 return ast;
1579 }
1580 /** @type {?} */
1581 const MAX_KEYFRAME_OFFSET = 1;
1582 /** @type {?} */
1583 let totalKeyframesWithOffsets = 0;
1584 /** @type {?} */
1585 const offsets = [];
1586 /** @type {?} */
1587 let offsetsOutOfOrder = false;
1588 /** @type {?} */
1589 let keyframesOutOfRange = false;
1590 /** @type {?} */
1591 let previousOffset = 0;
1592 /** @type {?} */
1593 const keyframes = metadata.steps.map((/**
1594 * @param {?} styles
1595 * @return {?}
1596 */
1597 styles => {
1598 /** @type {?} */
1599 const style = this._makeStyleAst(styles, context);
1600 /** @type {?} */
1601 let offsetVal = style.offset != null ? style.offset : consumeOffset(style.styles);
1602 /** @type {?} */
1603 let offset = 0;
1604 if (offsetVal != null) {
1605 totalKeyframesWithOffsets++;
1606 offset = style.offset = offsetVal;
1607 }
1608 keyframesOutOfRange = keyframesOutOfRange || offset < 0 || offset > 1;
1609 offsetsOutOfOrder = offsetsOutOfOrder || offset < previousOffset;
1610 previousOffset = offset;
1611 offsets.push(offset);
1612 return style;
1613 }));
1614 if (keyframesOutOfRange) {
1615 context.errors.push(`Please ensure that all keyframe offsets are between 0 and 1`);
1616 }
1617 if (offsetsOutOfOrder) {
1618 context.errors.push(`Please ensure that all keyframe offsets are in order`);
1619 }
1620 /** @type {?} */
1621 const length = metadata.steps.length;
1622 /** @type {?} */
1623 let generatedOffset = 0;
1624 if (totalKeyframesWithOffsets > 0 && totalKeyframesWithOffsets < length) {
1625 context.errors.push(`Not all style() steps within the declared keyframes() contain offsets`);
1626 }
1627 else if (totalKeyframesWithOffsets == 0) {
1628 generatedOffset = MAX_KEYFRAME_OFFSET / (length - 1);
1629 }
1630 /** @type {?} */
1631 const limit = length - 1;
1632 /** @type {?} */
1633 const currentTime = context.currentTime;
1634 /** @type {?} */
1635 const currentAnimateTimings = (/** @type {?} */ (context.currentAnimateTimings));
1636 /** @type {?} */
1637 const animateDuration = currentAnimateTimings.duration;
1638 keyframes.forEach((/**
1639 * @param {?} kf
1640 * @param {?} i
1641 * @return {?}
1642 */
1643 (kf, i) => {
1644 /** @type {?} */
1645 const offset = generatedOffset > 0 ? (i == limit ? 1 : (generatedOffset * i)) : offsets[i];
1646 /** @type {?} */
1647 const durationUpToThisFrame = offset * animateDuration;
1648 context.currentTime = currentTime + currentAnimateTimings.delay + durationUpToThisFrame;
1649 currentAnimateTimings.duration = durationUpToThisFrame;
1650 this._validateStyleAst(kf, context);
1651 kf.offset = offset;
1652 ast.styles.push(kf);
1653 }));
1654 return ast;
1655 }
1656 /**
1657 * @param {?} metadata
1658 * @param {?} context
1659 * @return {?}
1660 */
1661 visitReference(metadata, context) {
1662 return {
1663 type: 8 /* Reference */,
1664 animation: visitDslNode(this, normalizeAnimationEntry(metadata.animation), context),
1665 options: normalizeAnimationOptions(metadata.options)
1666 };
1667 }
1668 /**
1669 * @param {?} metadata
1670 * @param {?} context
1671 * @return {?}
1672 */
1673 visitAnimateChild(metadata, context) {
1674 context.depCount++;
1675 return {
1676 type: 9 /* AnimateChild */,
1677 options: normalizeAnimationOptions(metadata.options)
1678 };
1679 }
1680 /**
1681 * @param {?} metadata
1682 * @param {?} context
1683 * @return {?}
1684 */
1685 visitAnimateRef(metadata, context) {
1686 return {
1687 type: 10 /* AnimateRef */,
1688 animation: this.visitReference(metadata.animation, context),
1689 options: normalizeAnimationOptions(metadata.options)
1690 };
1691 }
1692 /**
1693 * @param {?} metadata
1694 * @param {?} context
1695 * @return {?}
1696 */
1697 visitQuery(metadata, context) {
1698 /** @type {?} */
1699 const parentSelector = (/** @type {?} */ (context.currentQuerySelector));
1700 /** @type {?} */
1701 const options = (/** @type {?} */ ((metadata.options || {})));
1702 context.queryCount++;
1703 context.currentQuery = metadata;
1704 const [selector, includeSelf] = normalizeSelector(metadata.selector);
1705 context.currentQuerySelector =
1706 parentSelector.length ? (parentSelector + ' ' + selector) : selector;
1707 getOrSetAsInMap(context.collectedStyles, context.currentQuerySelector, {});
1708 /** @type {?} */
1709 const animation = visitDslNode(this, normalizeAnimationEntry(metadata.animation), context);
1710 context.currentQuery = null;
1711 context.currentQuerySelector = parentSelector;
1712 return {
1713 type: 11 /* Query */,
1714 selector,
1715 limit: options.limit || 0,
1716 optional: !!options.optional, includeSelf, animation,
1717 originalSelector: metadata.selector,
1718 options: normalizeAnimationOptions(metadata.options)
1719 };
1720 }
1721 /**
1722 * @param {?} metadata
1723 * @param {?} context
1724 * @return {?}
1725 */
1726 visitStagger(metadata, context) {
1727 if (!context.currentQuery) {
1728 context.errors.push(`stagger() can only be used inside of query()`);
1729 }
1730 /** @type {?} */
1731 const timings = metadata.timings === 'full' ?
1732 { duration: 0, delay: 0, easing: 'full' } :
1733 resolveTiming(metadata.timings, context.errors, true);
1734 return {
1735 type: 12 /* Stagger */,
1736 animation: visitDslNode(this, normalizeAnimationEntry(metadata.animation), context), timings,
1737 options: null
1738 };
1739 }
1740}
1741if (false) {
1742 /**
1743 * @type {?}
1744 * @private
1745 */
1746 AnimationAstBuilderVisitor.prototype._driver;
1747}
1748/**
1749 * @param {?} selector
1750 * @return {?}
1751 */
1752function normalizeSelector(selector) {
1753 /** @type {?} */
1754 const hasAmpersand = selector.split(/\s*,\s*/).find((/**
1755 * @param {?} token
1756 * @return {?}
1757 */
1758 token => token == SELF_TOKEN)) ? true : false;
1759 if (hasAmpersand) {
1760 selector = selector.replace(SELF_TOKEN_REGEX, '');
1761 }
1762 // the :enter and :leave selectors are filled in at runtime during timeline building
1763 selector = selector.replace(/@\*/g, NG_TRIGGER_SELECTOR)
1764 .replace(/@\w+/g, (/**
1765 * @param {?} match
1766 * @return {?}
1767 */
1768 match => NG_TRIGGER_SELECTOR + '-' + match.substr(1)))
1769 .replace(/:animating/g, NG_ANIMATING_SELECTOR);
1770 return [selector, hasAmpersand];
1771}
1772/**
1773 * @param {?} obj
1774 * @return {?}
1775 */
1776function normalizeParams(obj) {
1777 return obj ? copyObj(obj) : null;
1778}
1779class AnimationAstBuilderContext {
1780 /**
1781 * @param {?} errors
1782 */
1783 constructor(errors) {
1784 this.errors = errors;
1785 this.queryCount = 0;
1786 this.depCount = 0;
1787 this.currentTransition = null;
1788 this.currentQuery = null;
1789 this.currentQuerySelector = null;
1790 this.currentAnimateTimings = null;
1791 this.currentTime = 0;
1792 this.collectedStyles = {};
1793 this.options = null;
1794 }
1795}
1796if (false) {
1797 /** @type {?} */
1798 AnimationAstBuilderContext.prototype.queryCount;
1799 /** @type {?} */
1800 AnimationAstBuilderContext.prototype.depCount;
1801 /** @type {?} */
1802 AnimationAstBuilderContext.prototype.currentTransition;
1803 /** @type {?} */
1804 AnimationAstBuilderContext.prototype.currentQuery;
1805 /** @type {?} */
1806 AnimationAstBuilderContext.prototype.currentQuerySelector;
1807 /** @type {?} */
1808 AnimationAstBuilderContext.prototype.currentAnimateTimings;
1809 /** @type {?} */
1810 AnimationAstBuilderContext.prototype.currentTime;
1811 /** @type {?} */
1812 AnimationAstBuilderContext.prototype.collectedStyles;
1813 /** @type {?} */
1814 AnimationAstBuilderContext.prototype.options;
1815 /** @type {?} */
1816 AnimationAstBuilderContext.prototype.errors;
1817}
1818/**
1819 * @param {?} styles
1820 * @return {?}
1821 */
1822function consumeOffset(styles) {
1823 if (typeof styles == 'string')
1824 return null;
1825 /** @type {?} */
1826 let offset = null;
1827 if (Array.isArray(styles)) {
1828 styles.forEach((/**
1829 * @param {?} styleTuple
1830 * @return {?}
1831 */
1832 styleTuple => {
1833 if (isObject(styleTuple) && styleTuple.hasOwnProperty('offset')) {
1834 /** @type {?} */
1835 const obj = (/** @type {?} */ (styleTuple));
1836 offset = parseFloat((/** @type {?} */ (obj['offset'])));
1837 delete obj['offset'];
1838 }
1839 }));
1840 }
1841 else if (isObject(styles) && styles.hasOwnProperty('offset')) {
1842 /** @type {?} */
1843 const obj = styles;
1844 offset = parseFloat((/** @type {?} */ (obj['offset'])));
1845 delete obj['offset'];
1846 }
1847 return offset;
1848}
1849/**
1850 * @param {?} value
1851 * @return {?}
1852 */
1853function isObject(value) {
1854 return !Array.isArray(value) && typeof value == 'object';
1855}
1856/**
1857 * @param {?} value
1858 * @param {?} errors
1859 * @return {?}
1860 */
1861function constructTimingAst(value, errors) {
1862 /** @type {?} */
1863 let timings = null;
1864 if (value.hasOwnProperty('duration')) {
1865 timings = (/** @type {?} */ (value));
1866 }
1867 else if (typeof value == 'number') {
1868 /** @type {?} */
1869 const duration = resolveTiming(value, errors).duration;
1870 return makeTimingAst(duration, 0, '');
1871 }
1872 /** @type {?} */
1873 const strValue = (/** @type {?} */ (value));
1874 /** @type {?} */
1875 const isDynamic = strValue.split(/\s+/).some((/**
1876 * @param {?} v
1877 * @return {?}
1878 */
1879 v => v.charAt(0) == '{' && v.charAt(1) == '{'));
1880 if (isDynamic) {
1881 /** @type {?} */
1882 const ast = (/** @type {?} */ (makeTimingAst(0, 0, '')));
1883 ast.dynamic = true;
1884 ast.strValue = strValue;
1885 return (/** @type {?} */ (ast));
1886 }
1887 timings = timings || resolveTiming(strValue, errors);
1888 return makeTimingAst(timings.duration, timings.delay, timings.easing);
1889}
1890/**
1891 * @param {?} options
1892 * @return {?}
1893 */
1894function normalizeAnimationOptions(options) {
1895 if (options) {
1896 options = copyObj(options);
1897 if (options['params']) {
1898 options['params'] = (/** @type {?} */ (normalizeParams(options['params'])));
1899 }
1900 }
1901 else {
1902 options = {};
1903 }
1904 return options;
1905}
1906/**
1907 * @param {?} duration
1908 * @param {?} delay
1909 * @param {?} easing
1910 * @return {?}
1911 */
1912function makeTimingAst(duration, delay, easing) {
1913 return { duration, delay, easing };
1914}
1915
1916/**
1917 * @fileoverview added by tsickle
1918 * Generated from: packages/animations/browser/src/dsl/animation_timeline_instruction.ts
1919 * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
1920 */
1921/**
1922 * @record
1923 */
1924function AnimationTimelineInstruction() { }
1925if (false) {
1926 /** @type {?} */
1927 AnimationTimelineInstruction.prototype.element;
1928 /** @type {?} */
1929 AnimationTimelineInstruction.prototype.keyframes;
1930 /** @type {?} */
1931 AnimationTimelineInstruction.prototype.preStyleProps;
1932 /** @type {?} */
1933 AnimationTimelineInstruction.prototype.postStyleProps;
1934 /** @type {?} */
1935 AnimationTimelineInstruction.prototype.duration;
1936 /** @type {?} */
1937 AnimationTimelineInstruction.prototype.delay;
1938 /** @type {?} */
1939 AnimationTimelineInstruction.prototype.totalTime;
1940 /** @type {?} */
1941 AnimationTimelineInstruction.prototype.easing;
1942 /** @type {?|undefined} */
1943 AnimationTimelineInstruction.prototype.stretchStartingKeyframe;
1944 /** @type {?} */
1945 AnimationTimelineInstruction.prototype.subTimeline;
1946}
1947/**
1948 * @param {?} element
1949 * @param {?} keyframes
1950 * @param {?} preStyleProps
1951 * @param {?} postStyleProps
1952 * @param {?} duration
1953 * @param {?} delay
1954 * @param {?=} easing
1955 * @param {?=} subTimeline
1956 * @return {?}
1957 */
1958function createTimelineInstruction(element, keyframes, preStyleProps, postStyleProps, duration, delay, easing = null, subTimeline = false) {
1959 return {
1960 type: 1 /* TimelineAnimation */,
1961 element,
1962 keyframes,
1963 preStyleProps,
1964 postStyleProps,
1965 duration,
1966 delay,
1967 totalTime: duration + delay, easing, subTimeline
1968 };
1969}
1970
1971/**
1972 * @fileoverview added by tsickle
1973 * Generated from: packages/animations/browser/src/dsl/element_instruction_map.ts
1974 * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
1975 */
1976class ElementInstructionMap {
1977 constructor() {
1978 this._map = new Map();
1979 }
1980 /**
1981 * @param {?} element
1982 * @return {?}
1983 */
1984 consume(element) {
1985 /** @type {?} */
1986 let instructions = this._map.get(element);
1987 if (instructions) {
1988 this._map.delete(element);
1989 }
1990 else {
1991 instructions = [];
1992 }
1993 return instructions;
1994 }
1995 /**
1996 * @param {?} element
1997 * @param {?} instructions
1998 * @return {?}
1999 */
2000 append(element, instructions) {
2001 /** @type {?} */
2002 let existingInstructions = this._map.get(element);
2003 if (!existingInstructions) {
2004 this._map.set(element, existingInstructions = []);
2005 }
2006 existingInstructions.push(...instructions);
2007 }
2008 /**
2009 * @param {?} element
2010 * @return {?}
2011 */
2012 has(element) { return this._map.has(element); }
2013 /**
2014 * @return {?}
2015 */
2016 clear() { this._map.clear(); }
2017}
2018if (false) {
2019 /**
2020 * @type {?}
2021 * @private
2022 */
2023 ElementInstructionMap.prototype._map;
2024}
2025
2026/**
2027 * @fileoverview added by tsickle
2028 * Generated from: packages/animations/browser/src/dsl/animation_timeline_builder.ts
2029 * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
2030 */
2031/** @type {?} */
2032const ONE_FRAME_IN_MILLISECONDS = 1;
2033/** @type {?} */
2034const ENTER_TOKEN = ':enter';
2035/** @type {?} */
2036const ENTER_TOKEN_REGEX = new RegExp(ENTER_TOKEN, 'g');
2037/** @type {?} */
2038const LEAVE_TOKEN = ':leave';
2039/** @type {?} */
2040const LEAVE_TOKEN_REGEX = new RegExp(LEAVE_TOKEN, 'g');
2041/*
2042 * The code within this file aims to generate web-animations-compatible keyframes from Angular's
2043 * animation DSL code.
2044 *
2045 * The code below will be converted from:
2046 *
2047 * ```
2048 * sequence([
2049 * style({ opacity: 0 }),
2050 * animate(1000, style({ opacity: 0 }))
2051 * ])
2052 * ```
2053 *
2054 * To:
2055 * ```
2056 * keyframes = [{ opacity: 0, offset: 0 }, { opacity: 1, offset: 1 }]
2057 * duration = 1000
2058 * delay = 0
2059 * easing = ''
2060 * ```
2061 *
2062 * For this operation to cover the combination of animation verbs (style, animate, group, etc...) a
2063 * combination of prototypical inheritance, AST traversal and merge-sort-like algorithms are used.
2064 *
2065 * [AST Traversal]
2066 * Each of the animation verbs, when executed, will return an string-map object representing what
2067 * type of action it is (style, animate, group, etc...) and the data associated with it. This means
2068 * that when functional composition mix of these functions is evaluated (like in the example above)
2069 * then it will end up producing a tree of objects representing the animation itself.
2070 *
2071 * When this animation object tree is processed by the visitor code below it will visit each of the
2072 * verb statements within the visitor. And during each visit it will build the context of the
2073 * animation keyframes by interacting with the `TimelineBuilder`.
2074 *
2075 * [TimelineBuilder]
2076 * This class is responsible for tracking the styles and building a series of keyframe objects for a
2077 * timeline between a start and end time. The builder starts off with an initial timeline and each
2078 * time the AST comes across a `group()`, `keyframes()` or a combination of the two wihtin a
2079 * `sequence()` then it will generate a sub timeline for each step as well as a new one after
2080 * they are complete.
2081 *
2082 * As the AST is traversed, the timing state on each of the timelines will be incremented. If a sub
2083 * timeline was created (based on one of the cases above) then the parent timeline will attempt to
2084 * merge the styles used within the sub timelines into itself (only with group() this will happen).
2085 * This happens with a merge operation (much like how the merge works in mergesort) and it will only
2086 * copy the most recently used styles from the sub timelines into the parent timeline. This ensures
2087 * that if the styles are used later on in another phase of the animation then they will be the most
2088 * up-to-date values.
2089 *
2090 * [How Missing Styles Are Updated]
2091 * Each timeline has a `backFill` property which is responsible for filling in new styles into
2092 * already processed keyframes if a new style shows up later within the animation sequence.
2093 *
2094 * ```
2095 * sequence([
2096 * style({ width: 0 }),
2097 * animate(1000, style({ width: 100 })),
2098 * animate(1000, style({ width: 200 })),
2099 * animate(1000, style({ width: 300 }))
2100 * animate(1000, style({ width: 400, height: 400 })) // notice how `height` doesn't exist anywhere
2101 * else
2102 * ])
2103 * ```
2104 *
2105 * What is happening here is that the `height` value is added later in the sequence, but is missing
2106 * from all previous animation steps. Therefore when a keyframe is created it would also be missing
2107 * from all previous keyframes up until where it is first used. For the timeline keyframe generation
2108 * to properly fill in the style it will place the previous value (the value from the parent
2109 * timeline) or a default value of `*` into the backFill object. Given that each of the keyframe
2110 * styles are objects that prototypically inhert from the backFill object, this means that if a
2111 * value is added into the backFill then it will automatically propagate any missing values to all
2112 * keyframes. Therefore the missing `height` value will be properly filled into the already
2113 * processed keyframes.
2114 *
2115 * When a sub-timeline is created it will have its own backFill property. This is done so that
2116 * styles present within the sub-timeline do not accidentally seep into the previous/future timeline
2117 * keyframes
2118 *
2119 * (For prototypically-inherited contents to be detected a `for(i in obj)` loop must be used.)
2120 *
2121 * [Validation]
2122 * The code in this file is not responsible for validation. That functionality happens with within
2123 * the `AnimationValidatorVisitor` code.
2124 */
2125/**
2126 * @param {?} driver
2127 * @param {?} rootElement
2128 * @param {?} ast
2129 * @param {?} enterClassName
2130 * @param {?} leaveClassName
2131 * @param {?=} startingStyles
2132 * @param {?=} finalStyles
2133 * @param {?=} options
2134 * @param {?=} subInstructions
2135 * @param {?=} errors
2136 * @return {?}
2137 */
2138function buildAnimationTimelines(driver, rootElement, ast, enterClassName, leaveClassName, startingStyles = {}, finalStyles = {}, options, subInstructions, errors = []) {
2139 return new AnimationTimelineBuilderVisitor().buildKeyframes(driver, rootElement, ast, enterClassName, leaveClassName, startingStyles, finalStyles, options, subInstructions, errors);
2140}
2141class AnimationTimelineBuilderVisitor {
2142 /**
2143 * @param {?} driver
2144 * @param {?} rootElement
2145 * @param {?} ast
2146 * @param {?} enterClassName
2147 * @param {?} leaveClassName
2148 * @param {?} startingStyles
2149 * @param {?} finalStyles
2150 * @param {?} options
2151 * @param {?=} subInstructions
2152 * @param {?=} errors
2153 * @return {?}
2154 */
2155 buildKeyframes(driver, rootElement, ast, enterClassName, leaveClassName, startingStyles, finalStyles, options, subInstructions, errors = []) {
2156 subInstructions = subInstructions || new ElementInstructionMap();
2157 /** @type {?} */
2158 const context = new AnimationTimelineContext(driver, rootElement, subInstructions, enterClassName, leaveClassName, errors, []);
2159 context.options = options;
2160 context.currentTimeline.setStyles([startingStyles], null, context.errors, options);
2161 visitDslNode(this, ast, context);
2162 // this checks to see if an actual animation happened
2163 /** @type {?} */
2164 const timelines = context.timelines.filter((/**
2165 * @param {?} timeline
2166 * @return {?}
2167 */
2168 timeline => timeline.containsAnimation()));
2169 if (timelines.length && Object.keys(finalStyles).length) {
2170 /** @type {?} */
2171 const tl = timelines[timelines.length - 1];
2172 if (!tl.allowOnlyTimelineStyles()) {
2173 tl.setStyles([finalStyles], null, context.errors, options);
2174 }
2175 }
2176 return timelines.length ? timelines.map((/**
2177 * @param {?} timeline
2178 * @return {?}
2179 */
2180 timeline => timeline.buildKeyframes())) :
2181 [createTimelineInstruction(rootElement, [], [], [], 0, 0, '', false)];
2182 }
2183 /**
2184 * @param {?} ast
2185 * @param {?} context
2186 * @return {?}
2187 */
2188 visitTrigger(ast, context) {
2189 // these values are not visited in this AST
2190 }
2191 /**
2192 * @param {?} ast
2193 * @param {?} context
2194 * @return {?}
2195 */
2196 visitState(ast, context) {
2197 // these values are not visited in this AST
2198 }
2199 /**
2200 * @param {?} ast
2201 * @param {?} context
2202 * @return {?}
2203 */
2204 visitTransition(ast, context) {
2205 // these values are not visited in this AST
2206 }
2207 /**
2208 * @param {?} ast
2209 * @param {?} context
2210 * @return {?}
2211 */
2212 visitAnimateChild(ast, context) {
2213 /** @type {?} */
2214 const elementInstructions = context.subInstructions.consume(context.element);
2215 if (elementInstructions) {
2216 /** @type {?} */
2217 const innerContext = context.createSubContext(ast.options);
2218 /** @type {?} */
2219 const startTime = context.currentTimeline.currentTime;
2220 /** @type {?} */
2221 const endTime = this._visitSubInstructions(elementInstructions, innerContext, (/** @type {?} */ (innerContext.options)));
2222 if (startTime != endTime) {
2223 // we do this on the upper context because we created a sub context for
2224 // the sub child animations
2225 context.transformIntoNewTimeline(endTime);
2226 }
2227 }
2228 context.previousNode = ast;
2229 }
2230 /**
2231 * @param {?} ast
2232 * @param {?} context
2233 * @return {?}
2234 */
2235 visitAnimateRef(ast, context) {
2236 /** @type {?} */
2237 const innerContext = context.createSubContext(ast.options);
2238 innerContext.transformIntoNewTimeline();
2239 this.visitReference(ast.animation, innerContext);
2240 context.transformIntoNewTimeline(innerContext.currentTimeline.currentTime);
2241 context.previousNode = ast;
2242 }
2243 /**
2244 * @private
2245 * @param {?} instructions
2246 * @param {?} context
2247 * @param {?} options
2248 * @return {?}
2249 */
2250 _visitSubInstructions(instructions, context, options) {
2251 /** @type {?} */
2252 const startTime = context.currentTimeline.currentTime;
2253 /** @type {?} */
2254 let furthestTime = startTime;
2255 // this is a special-case for when a user wants to skip a sub
2256 // animation from being fired entirely.
2257 /** @type {?} */
2258 const duration = options.duration != null ? resolveTimingValue(options.duration) : null;
2259 /** @type {?} */
2260 const delay = options.delay != null ? resolveTimingValue(options.delay) : null;
2261 if (duration !== 0) {
2262 instructions.forEach((/**
2263 * @param {?} instruction
2264 * @return {?}
2265 */
2266 instruction => {
2267 /** @type {?} */
2268 const instructionTimings = context.appendInstructionToTimeline(instruction, duration, delay);
2269 furthestTime =
2270 Math.max(furthestTime, instructionTimings.duration + instructionTimings.delay);
2271 }));
2272 }
2273 return furthestTime;
2274 }
2275 /**
2276 * @param {?} ast
2277 * @param {?} context
2278 * @return {?}
2279 */
2280 visitReference(ast, context) {
2281 context.updateOptions(ast.options, true);
2282 visitDslNode(this, ast.animation, context);
2283 context.previousNode = ast;
2284 }
2285 /**
2286 * @param {?} ast
2287 * @param {?} context
2288 * @return {?}
2289 */
2290 visitSequence(ast, context) {
2291 /** @type {?} */
2292 const subContextCount = context.subContextCount;
2293 /** @type {?} */
2294 let ctx = context;
2295 /** @type {?} */
2296 const options = ast.options;
2297 if (options && (options.params || options.delay)) {
2298 ctx = context.createSubContext(options);
2299 ctx.transformIntoNewTimeline();
2300 if (options.delay != null) {
2301 if (ctx.previousNode.type == 6 /* Style */) {
2302 ctx.currentTimeline.snapshotCurrentStyles();
2303 ctx.previousNode = DEFAULT_NOOP_PREVIOUS_NODE;
2304 }
2305 /** @type {?} */
2306 const delay = resolveTimingValue(options.delay);
2307 ctx.delayNextStep(delay);
2308 }
2309 }
2310 if (ast.steps.length) {
2311 ast.steps.forEach((/**
2312 * @param {?} s
2313 * @return {?}
2314 */
2315 s => visitDslNode(this, s, ctx)));
2316 // this is here just incase the inner steps only contain or end with a style() call
2317 ctx.currentTimeline.applyStylesToKeyframe();
2318 // this means that some animation function within the sequence
2319 // ended up creating a sub timeline (which means the current
2320 // timeline cannot overlap with the contents of the sequence)
2321 if (ctx.subContextCount > subContextCount) {
2322 ctx.transformIntoNewTimeline();
2323 }
2324 }
2325 context.previousNode = ast;
2326 }
2327 /**
2328 * @param {?} ast
2329 * @param {?} context
2330 * @return {?}
2331 */
2332 visitGroup(ast, context) {
2333 /** @type {?} */
2334 const innerTimelines = [];
2335 /** @type {?} */
2336 let furthestTime = context.currentTimeline.currentTime;
2337 /** @type {?} */
2338 const delay = ast.options && ast.options.delay ? resolveTimingValue(ast.options.delay) : 0;
2339 ast.steps.forEach((/**
2340 * @param {?} s
2341 * @return {?}
2342 */
2343 s => {
2344 /** @type {?} */
2345 const innerContext = context.createSubContext(ast.options);
2346 if (delay) {
2347 innerContext.delayNextStep(delay);
2348 }
2349 visitDslNode(this, s, innerContext);
2350 furthestTime = Math.max(furthestTime, innerContext.currentTimeline.currentTime);
2351 innerTimelines.push(innerContext.currentTimeline);
2352 }));
2353 // this operation is run after the AST loop because otherwise
2354 // if the parent timeline's collected styles were updated then
2355 // it would pass in invalid data into the new-to-be forked items
2356 innerTimelines.forEach((/**
2357 * @param {?} timeline
2358 * @return {?}
2359 */
2360 timeline => context.currentTimeline.mergeTimelineCollectedStyles(timeline)));
2361 context.transformIntoNewTimeline(furthestTime);
2362 context.previousNode = ast;
2363 }
2364 /**
2365 * @private
2366 * @param {?} ast
2367 * @param {?} context
2368 * @return {?}
2369 */
2370 _visitTiming(ast, context) {
2371 if (((/** @type {?} */ (ast))).dynamic) {
2372 /** @type {?} */
2373 const strValue = ((/** @type {?} */ (ast))).strValue;
2374 /** @type {?} */
2375 const timingValue = context.params ? interpolateParams(strValue, context.params, context.errors) : strValue;
2376 return resolveTiming(timingValue, context.errors);
2377 }
2378 else {
2379 return { duration: ast.duration, delay: ast.delay, easing: ast.easing };
2380 }
2381 }
2382 /**
2383 * @param {?} ast
2384 * @param {?} context
2385 * @return {?}
2386 */
2387 visitAnimate(ast, context) {
2388 /** @type {?} */
2389 const timings = context.currentAnimateTimings = this._visitTiming(ast.timings, context);
2390 /** @type {?} */
2391 const timeline = context.currentTimeline;
2392 if (timings.delay) {
2393 context.incrementTime(timings.delay);
2394 timeline.snapshotCurrentStyles();
2395 }
2396 /** @type {?} */
2397 const style = ast.style;
2398 if (style.type == 5 /* Keyframes */) {
2399 this.visitKeyframes(style, context);
2400 }
2401 else {
2402 context.incrementTime(timings.duration);
2403 this.visitStyle((/** @type {?} */ (style)), context);
2404 timeline.applyStylesToKeyframe();
2405 }
2406 context.currentAnimateTimings = null;
2407 context.previousNode = ast;
2408 }
2409 /**
2410 * @param {?} ast
2411 * @param {?} context
2412 * @return {?}
2413 */
2414 visitStyle(ast, context) {
2415 /** @type {?} */
2416 const timeline = context.currentTimeline;
2417 /** @type {?} */
2418 const timings = (/** @type {?} */ (context.currentAnimateTimings));
2419 // this is a special case for when a style() call
2420 // directly follows an animate() call (but not inside of an animate() call)
2421 if (!timings && timeline.getCurrentStyleProperties().length) {
2422 timeline.forwardFrame();
2423 }
2424 /** @type {?} */
2425 const easing = (timings && timings.easing) || ast.easing;
2426 if (ast.isEmptyStep) {
2427 timeline.applyEmptyStep(easing);
2428 }
2429 else {
2430 timeline.setStyles(ast.styles, easing, context.errors, context.options);
2431 }
2432 context.previousNode = ast;
2433 }
2434 /**
2435 * @param {?} ast
2436 * @param {?} context
2437 * @return {?}
2438 */
2439 visitKeyframes(ast, context) {
2440 /** @type {?} */
2441 const currentAnimateTimings = (/** @type {?} */ (context.currentAnimateTimings));
2442 /** @type {?} */
2443 const startTime = ((/** @type {?} */ (context.currentTimeline))).duration;
2444 /** @type {?} */
2445 const duration = currentAnimateTimings.duration;
2446 /** @type {?} */
2447 const innerContext = context.createSubContext();
2448 /** @type {?} */
2449 const innerTimeline = innerContext.currentTimeline;
2450 innerTimeline.easing = currentAnimateTimings.easing;
2451 ast.styles.forEach((/**
2452 * @param {?} step
2453 * @return {?}
2454 */
2455 step => {
2456 /** @type {?} */
2457 const offset = step.offset || 0;
2458 innerTimeline.forwardTime(offset * duration);
2459 innerTimeline.setStyles(step.styles, step.easing, context.errors, context.options);
2460 innerTimeline.applyStylesToKeyframe();
2461 }));
2462 // this will ensure that the parent timeline gets all the styles from
2463 // the child even if the new timeline below is not used
2464 context.currentTimeline.mergeTimelineCollectedStyles(innerTimeline);
2465 // we do this because the window between this timeline and the sub timeline
2466 // should ensure that the styles within are exactly the same as they were before
2467 context.transformIntoNewTimeline(startTime + duration);
2468 context.previousNode = ast;
2469 }
2470 /**
2471 * @param {?} ast
2472 * @param {?} context
2473 * @return {?}
2474 */
2475 visitQuery(ast, context) {
2476 // in the event that the first step before this is a style step we need
2477 // to ensure the styles are applied before the children are animated
2478 /** @type {?} */
2479 const startTime = context.currentTimeline.currentTime;
2480 /** @type {?} */
2481 const options = (/** @type {?} */ ((ast.options || {})));
2482 /** @type {?} */
2483 const delay = options.delay ? resolveTimingValue(options.delay) : 0;
2484 if (delay && (context.previousNode.type === 6 /* Style */ ||
2485 (startTime == 0 && context.currentTimeline.getCurrentStyleProperties().length))) {
2486 context.currentTimeline.snapshotCurrentStyles();
2487 context.previousNode = DEFAULT_NOOP_PREVIOUS_NODE;
2488 }
2489 /** @type {?} */
2490 let furthestTime = startTime;
2491 /** @type {?} */
2492 const elms = context.invokeQuery(ast.selector, ast.originalSelector, ast.limit, ast.includeSelf, options.optional ? true : false, context.errors);
2493 context.currentQueryTotal = elms.length;
2494 /** @type {?} */
2495 let sameElementTimeline = null;
2496 elms.forEach((/**
2497 * @param {?} element
2498 * @param {?} i
2499 * @return {?}
2500 */
2501 (element, i) => {
2502 context.currentQueryIndex = i;
2503 /** @type {?} */
2504 const innerContext = context.createSubContext(ast.options, element);
2505 if (delay) {
2506 innerContext.delayNextStep(delay);
2507 }
2508 if (element === context.element) {
2509 sameElementTimeline = innerContext.currentTimeline;
2510 }
2511 visitDslNode(this, ast.animation, innerContext);
2512 // this is here just incase the inner steps only contain or end
2513 // with a style() call (which is here to signal that this is a preparatory
2514 // call to style an element before it is animated again)
2515 innerContext.currentTimeline.applyStylesToKeyframe();
2516 /** @type {?} */
2517 const endTime = innerContext.currentTimeline.currentTime;
2518 furthestTime = Math.max(furthestTime, endTime);
2519 }));
2520 context.currentQueryIndex = 0;
2521 context.currentQueryTotal = 0;
2522 context.transformIntoNewTimeline(furthestTime);
2523 if (sameElementTimeline) {
2524 context.currentTimeline.mergeTimelineCollectedStyles(sameElementTimeline);
2525 context.currentTimeline.snapshotCurrentStyles();
2526 }
2527 context.previousNode = ast;
2528 }
2529 /**
2530 * @param {?} ast
2531 * @param {?} context
2532 * @return {?}
2533 */
2534 visitStagger(ast, context) {
2535 /** @type {?} */
2536 const parentContext = (/** @type {?} */ (context.parentContext));
2537 /** @type {?} */
2538 const tl = context.currentTimeline;
2539 /** @type {?} */
2540 const timings = ast.timings;
2541 /** @type {?} */
2542 const duration = Math.abs(timings.duration);
2543 /** @type {?} */
2544 const maxTime = duration * (context.currentQueryTotal - 1);
2545 /** @type {?} */
2546 let delay = duration * context.currentQueryIndex;
2547 /** @type {?} */
2548 let staggerTransformer = timings.duration < 0 ? 'reverse' : timings.easing;
2549 switch (staggerTransformer) {
2550 case 'reverse':
2551 delay = maxTime - delay;
2552 break;
2553 case 'full':
2554 delay = parentContext.currentStaggerTime;
2555 break;
2556 }
2557 /** @type {?} */
2558 const timeline = context.currentTimeline;
2559 if (delay) {
2560 timeline.delayNextStep(delay);
2561 }
2562 /** @type {?} */
2563 const startingTime = timeline.currentTime;
2564 visitDslNode(this, ast.animation, context);
2565 context.previousNode = ast;
2566 // time = duration + delay
2567 // the reason why this computation is so complex is because
2568 // the inner timeline may either have a delay value or a stretched
2569 // keyframe depending on if a subtimeline is not used or is used.
2570 parentContext.currentStaggerTime =
2571 (tl.currentTime - startingTime) + (tl.startTime - parentContext.currentTimeline.startTime);
2572 }
2573}
2574/** @type {?} */
2575const DEFAULT_NOOP_PREVIOUS_NODE = (/** @type {?} */ ({}));
2576class AnimationTimelineContext {
2577 /**
2578 * @param {?} _driver
2579 * @param {?} element
2580 * @param {?} subInstructions
2581 * @param {?} _enterClassName
2582 * @param {?} _leaveClassName
2583 * @param {?} errors
2584 * @param {?} timelines
2585 * @param {?=} initialTimeline
2586 */
2587 constructor(_driver, element, subInstructions, _enterClassName, _leaveClassName, errors, timelines, initialTimeline) {
2588 this._driver = _driver;
2589 this.element = element;
2590 this.subInstructions = subInstructions;
2591 this._enterClassName = _enterClassName;
2592 this._leaveClassName = _leaveClassName;
2593 this.errors = errors;
2594 this.timelines = timelines;
2595 this.parentContext = null;
2596 this.currentAnimateTimings = null;
2597 this.previousNode = DEFAULT_NOOP_PREVIOUS_NODE;
2598 this.subContextCount = 0;
2599 this.options = {};
2600 this.currentQueryIndex = 0;
2601 this.currentQueryTotal = 0;
2602 this.currentStaggerTime = 0;
2603 this.currentTimeline = initialTimeline || new TimelineBuilder(this._driver, element, 0);
2604 timelines.push(this.currentTimeline);
2605 }
2606 /**
2607 * @return {?}
2608 */
2609 get params() { return this.options.params; }
2610 /**
2611 * @param {?} options
2612 * @param {?=} skipIfExists
2613 * @return {?}
2614 */
2615 updateOptions(options, skipIfExists) {
2616 if (!options)
2617 return;
2618 /** @type {?} */
2619 const newOptions = (/** @type {?} */ (options));
2620 /** @type {?} */
2621 let optionsToUpdate = this.options;
2622 // NOTE: this will get patched up when other animation methods support duration overrides
2623 if (newOptions.duration != null) {
2624 ((/** @type {?} */ (optionsToUpdate))).duration = resolveTimingValue(newOptions.duration);
2625 }
2626 if (newOptions.delay != null) {
2627 optionsToUpdate.delay = resolveTimingValue(newOptions.delay);
2628 }
2629 /** @type {?} */
2630 const newParams = newOptions.params;
2631 if (newParams) {
2632 /** @type {?} */
2633 let paramsToUpdate = (/** @type {?} */ (optionsToUpdate.params));
2634 if (!paramsToUpdate) {
2635 paramsToUpdate = this.options.params = {};
2636 }
2637 Object.keys(newParams).forEach((/**
2638 * @param {?} name
2639 * @return {?}
2640 */
2641 name => {
2642 if (!skipIfExists || !paramsToUpdate.hasOwnProperty(name)) {
2643 paramsToUpdate[name] = interpolateParams(newParams[name], paramsToUpdate, this.errors);
2644 }
2645 }));
2646 }
2647 }
2648 /**
2649 * @private
2650 * @return {?}
2651 */
2652 _copyOptions() {
2653 /** @type {?} */
2654 const options = {};
2655 if (this.options) {
2656 /** @type {?} */
2657 const oldParams = this.options.params;
2658 if (oldParams) {
2659 /** @type {?} */
2660 const params = options['params'] = {};
2661 Object.keys(oldParams).forEach((/**
2662 * @param {?} name
2663 * @return {?}
2664 */
2665 name => { params[name] = oldParams[name]; }));
2666 }
2667 }
2668 return options;
2669 }
2670 /**
2671 * @param {?=} options
2672 * @param {?=} element
2673 * @param {?=} newTime
2674 * @return {?}
2675 */
2676 createSubContext(options = null, element, newTime) {
2677 /** @type {?} */
2678 const target = element || this.element;
2679 /** @type {?} */
2680 const context = new AnimationTimelineContext(this._driver, target, this.subInstructions, this._enterClassName, this._leaveClassName, this.errors, this.timelines, this.currentTimeline.fork(target, newTime || 0));
2681 context.previousNode = this.previousNode;
2682 context.currentAnimateTimings = this.currentAnimateTimings;
2683 context.options = this._copyOptions();
2684 context.updateOptions(options);
2685 context.currentQueryIndex = this.currentQueryIndex;
2686 context.currentQueryTotal = this.currentQueryTotal;
2687 context.parentContext = this;
2688 this.subContextCount++;
2689 return context;
2690 }
2691 /**
2692 * @param {?=} newTime
2693 * @return {?}
2694 */
2695 transformIntoNewTimeline(newTime) {
2696 this.previousNode = DEFAULT_NOOP_PREVIOUS_NODE;
2697 this.currentTimeline = this.currentTimeline.fork(this.element, newTime);
2698 this.timelines.push(this.currentTimeline);
2699 return this.currentTimeline;
2700 }
2701 /**
2702 * @param {?} instruction
2703 * @param {?} duration
2704 * @param {?} delay
2705 * @return {?}
2706 */
2707 appendInstructionToTimeline(instruction, duration, delay) {
2708 /** @type {?} */
2709 const updatedTimings = {
2710 duration: duration != null ? duration : instruction.duration,
2711 delay: this.currentTimeline.currentTime + (delay != null ? delay : 0) + instruction.delay,
2712 easing: ''
2713 };
2714 /** @type {?} */
2715 const builder = new SubTimelineBuilder(this._driver, instruction.element, instruction.keyframes, instruction.preStyleProps, instruction.postStyleProps, updatedTimings, instruction.stretchStartingKeyframe);
2716 this.timelines.push(builder);
2717 return updatedTimings;
2718 }
2719 /**
2720 * @param {?} time
2721 * @return {?}
2722 */
2723 incrementTime(time) {
2724 this.currentTimeline.forwardTime(this.currentTimeline.duration + time);
2725 }
2726 /**
2727 * @param {?} delay
2728 * @return {?}
2729 */
2730 delayNextStep(delay) {
2731 // negative delays are not yet supported
2732 if (delay > 0) {
2733 this.currentTimeline.delayNextStep(delay);
2734 }
2735 }
2736 /**
2737 * @param {?} selector
2738 * @param {?} originalSelector
2739 * @param {?} limit
2740 * @param {?} includeSelf
2741 * @param {?} optional
2742 * @param {?} errors
2743 * @return {?}
2744 */
2745 invokeQuery(selector, originalSelector, limit, includeSelf, optional, errors) {
2746 /** @type {?} */
2747 let results = [];
2748 if (includeSelf) {
2749 results.push(this.element);
2750 }
2751 if (selector.length > 0) { // if :self is only used then the selector is empty
2752 selector = selector.replace(ENTER_TOKEN_REGEX, '.' + this._enterClassName);
2753 selector = selector.replace(LEAVE_TOKEN_REGEX, '.' + this._leaveClassName);
2754 /** @type {?} */
2755 const multi = limit != 1;
2756 /** @type {?} */
2757 let elements = this._driver.query(this.element, selector, multi);
2758 if (limit !== 0) {
2759 elements = limit < 0 ? elements.slice(elements.length + limit, elements.length) :
2760 elements.slice(0, limit);
2761 }
2762 results.push(...elements);
2763 }
2764 if (!optional && results.length == 0) {
2765 errors.push(`\`query("${originalSelector}")\` returned zero elements. (Use \`query("${originalSelector}", { optional: true })\` if you wish to allow this.)`);
2766 }
2767 return results;
2768 }
2769}
2770if (false) {
2771 /** @type {?} */
2772 AnimationTimelineContext.prototype.parentContext;
2773 /** @type {?} */
2774 AnimationTimelineContext.prototype.currentTimeline;
2775 /** @type {?} */
2776 AnimationTimelineContext.prototype.currentAnimateTimings;
2777 /** @type {?} */
2778 AnimationTimelineContext.prototype.previousNode;
2779 /** @type {?} */
2780 AnimationTimelineContext.prototype.subContextCount;
2781 /** @type {?} */
2782 AnimationTimelineContext.prototype.options;
2783 /** @type {?} */
2784 AnimationTimelineContext.prototype.currentQueryIndex;
2785 /** @type {?} */
2786 AnimationTimelineContext.prototype.currentQueryTotal;
2787 /** @type {?} */
2788 AnimationTimelineContext.prototype.currentStaggerTime;
2789 /**
2790 * @type {?}
2791 * @private
2792 */
2793 AnimationTimelineContext.prototype._driver;
2794 /** @type {?} */
2795 AnimationTimelineContext.prototype.element;
2796 /** @type {?} */
2797 AnimationTimelineContext.prototype.subInstructions;
2798 /**
2799 * @type {?}
2800 * @private
2801 */
2802 AnimationTimelineContext.prototype._enterClassName;
2803 /**
2804 * @type {?}
2805 * @private
2806 */
2807 AnimationTimelineContext.prototype._leaveClassName;
2808 /** @type {?} */
2809 AnimationTimelineContext.prototype.errors;
2810 /** @type {?} */
2811 AnimationTimelineContext.prototype.timelines;
2812}
2813class TimelineBuilder {
2814 /**
2815 * @param {?} _driver
2816 * @param {?} element
2817 * @param {?} startTime
2818 * @param {?=} _elementTimelineStylesLookup
2819 */
2820 constructor(_driver, element, startTime, _elementTimelineStylesLookup) {
2821 this._driver = _driver;
2822 this.element = element;
2823 this.startTime = startTime;
2824 this._elementTimelineStylesLookup = _elementTimelineStylesLookup;
2825 this.duration = 0;
2826 this._previousKeyframe = {};
2827 this._currentKeyframe = {};
2828 this._keyframes = new Map();
2829 this._styleSummary = {};
2830 this._pendingStyles = {};
2831 this._backFill = {};
2832 this._currentEmptyStepKeyframe = null;
2833 if (!this._elementTimelineStylesLookup) {
2834 this._elementTimelineStylesLookup = new Map();
2835 }
2836 this._localTimelineStyles = Object.create(this._backFill, {});
2837 this._globalTimelineStyles = (/** @type {?} */ (this._elementTimelineStylesLookup.get(element)));
2838 if (!this._globalTimelineStyles) {
2839 this._globalTimelineStyles = this._localTimelineStyles;
2840 this._elementTimelineStylesLookup.set(element, this._localTimelineStyles);
2841 }
2842 this._loadKeyframe();
2843 }
2844 /**
2845 * @return {?}
2846 */
2847 containsAnimation() {
2848 switch (this._keyframes.size) {
2849 case 0:
2850 return false;
2851 case 1:
2852 return this.getCurrentStyleProperties().length > 0;
2853 default:
2854 return true;
2855 }
2856 }
2857 /**
2858 * @return {?}
2859 */
2860 getCurrentStyleProperties() { return Object.keys(this._currentKeyframe); }
2861 /**
2862 * @return {?}
2863 */
2864 get currentTime() { return this.startTime + this.duration; }
2865 /**
2866 * @param {?} delay
2867 * @return {?}
2868 */
2869 delayNextStep(delay) {
2870 // in the event that a style() step is placed right before a stagger()
2871 // and that style() step is the very first style() value in the animation
2872 // then we need to make a copy of the keyframe [0, copy, 1] so that the delay
2873 // properly applies the style() values to work with the stagger...
2874 /** @type {?} */
2875 const hasPreStyleStep = this._keyframes.size == 1 && Object.keys(this._pendingStyles).length;
2876 if (this.duration || hasPreStyleStep) {
2877 this.forwardTime(this.currentTime + delay);
2878 if (hasPreStyleStep) {
2879 this.snapshotCurrentStyles();
2880 }
2881 }
2882 else {
2883 this.startTime += delay;
2884 }
2885 }
2886 /**
2887 * @param {?} element
2888 * @param {?=} currentTime
2889 * @return {?}
2890 */
2891 fork(element, currentTime) {
2892 this.applyStylesToKeyframe();
2893 return new TimelineBuilder(this._driver, element, currentTime || this.currentTime, this._elementTimelineStylesLookup);
2894 }
2895 /**
2896 * @private
2897 * @return {?}
2898 */
2899 _loadKeyframe() {
2900 if (this._currentKeyframe) {
2901 this._previousKeyframe = this._currentKeyframe;
2902 }
2903 this._currentKeyframe = (/** @type {?} */ (this._keyframes.get(this.duration)));
2904 if (!this._currentKeyframe) {
2905 this._currentKeyframe = Object.create(this._backFill, {});
2906 this._keyframes.set(this.duration, this._currentKeyframe);
2907 }
2908 }
2909 /**
2910 * @return {?}
2911 */
2912 forwardFrame() {
2913 this.duration += ONE_FRAME_IN_MILLISECONDS;
2914 this._loadKeyframe();
2915 }
2916 /**
2917 * @param {?} time
2918 * @return {?}
2919 */
2920 forwardTime(time) {
2921 this.applyStylesToKeyframe();
2922 this.duration = time;
2923 this._loadKeyframe();
2924 }
2925 /**
2926 * @private
2927 * @param {?} prop
2928 * @param {?} value
2929 * @return {?}
2930 */
2931 _updateStyle(prop, value) {
2932 this._localTimelineStyles[prop] = value;
2933 this._globalTimelineStyles[prop] = value;
2934 this._styleSummary[prop] = { time: this.currentTime, value };
2935 }
2936 /**
2937 * @return {?}
2938 */
2939 allowOnlyTimelineStyles() { return this._currentEmptyStepKeyframe !== this._currentKeyframe; }
2940 /**
2941 * @param {?} easing
2942 * @return {?}
2943 */
2944 applyEmptyStep(easing) {
2945 if (easing) {
2946 this._previousKeyframe['easing'] = easing;
2947 }
2948 // special case for animate(duration):
2949 // all missing styles are filled with a `*` value then
2950 // if any destination styles are filled in later on the same
2951 // keyframe then they will override the overridden styles
2952 // We use `_globalTimelineStyles` here because there may be
2953 // styles in previous keyframes that are not present in this timeline
2954 Object.keys(this._globalTimelineStyles).forEach((/**
2955 * @param {?} prop
2956 * @return {?}
2957 */
2958 prop => {
2959 this._backFill[prop] = this._globalTimelineStyles[prop] || AUTO_STYLE;
2960 this._currentKeyframe[prop] = AUTO_STYLE;
2961 }));
2962 this._currentEmptyStepKeyframe = this._currentKeyframe;
2963 }
2964 /**
2965 * @param {?} input
2966 * @param {?} easing
2967 * @param {?} errors
2968 * @param {?=} options
2969 * @return {?}
2970 */
2971 setStyles(input, easing, errors, options) {
2972 if (easing) {
2973 this._previousKeyframe['easing'] = easing;
2974 }
2975 /** @type {?} */
2976 const params = (options && options.params) || {};
2977 /** @type {?} */
2978 const styles = flattenStyles(input, this._globalTimelineStyles);
2979 Object.keys(styles).forEach((/**
2980 * @param {?} prop
2981 * @return {?}
2982 */
2983 prop => {
2984 /** @type {?} */
2985 const val = interpolateParams(styles[prop], params, errors);
2986 this._pendingStyles[prop] = val;
2987 if (!this._localTimelineStyles.hasOwnProperty(prop)) {
2988 this._backFill[prop] = this._globalTimelineStyles.hasOwnProperty(prop) ?
2989 this._globalTimelineStyles[prop] :
2990 AUTO_STYLE;
2991 }
2992 this._updateStyle(prop, val);
2993 }));
2994 }
2995 /**
2996 * @return {?}
2997 */
2998 applyStylesToKeyframe() {
2999 /** @type {?} */
3000 const styles = this._pendingStyles;
3001 /** @type {?} */
3002 const props = Object.keys(styles);
3003 if (props.length == 0)
3004 return;
3005 this._pendingStyles = {};
3006 props.forEach((/**
3007 * @param {?} prop
3008 * @return {?}
3009 */
3010 prop => {
3011 /** @type {?} */
3012 const val = styles[prop];
3013 this._currentKeyframe[prop] = val;
3014 }));
3015 Object.keys(this._localTimelineStyles).forEach((/**
3016 * @param {?} prop
3017 * @return {?}
3018 */
3019 prop => {
3020 if (!this._currentKeyframe.hasOwnProperty(prop)) {
3021 this._currentKeyframe[prop] = this._localTimelineStyles[prop];
3022 }
3023 }));
3024 }
3025 /**
3026 * @return {?}
3027 */
3028 snapshotCurrentStyles() {
3029 Object.keys(this._localTimelineStyles).forEach((/**
3030 * @param {?} prop
3031 * @return {?}
3032 */
3033 prop => {
3034 /** @type {?} */
3035 const val = this._localTimelineStyles[prop];
3036 this._pendingStyles[prop] = val;
3037 this._updateStyle(prop, val);
3038 }));
3039 }
3040 /**
3041 * @return {?}
3042 */
3043 getFinalKeyframe() { return this._keyframes.get(this.duration); }
3044 /**
3045 * @return {?}
3046 */
3047 get properties() {
3048 /** @type {?} */
3049 const properties = [];
3050 for (let prop in this._currentKeyframe) {
3051 properties.push(prop);
3052 }
3053 return properties;
3054 }
3055 /**
3056 * @param {?} timeline
3057 * @return {?}
3058 */
3059 mergeTimelineCollectedStyles(timeline) {
3060 Object.keys(timeline._styleSummary).forEach((/**
3061 * @param {?} prop
3062 * @return {?}
3063 */
3064 prop => {
3065 /** @type {?} */
3066 const details0 = this._styleSummary[prop];
3067 /** @type {?} */
3068 const details1 = timeline._styleSummary[prop];
3069 if (!details0 || details1.time > details0.time) {
3070 this._updateStyle(prop, details1.value);
3071 }
3072 }));
3073 }
3074 /**
3075 * @return {?}
3076 */
3077 buildKeyframes() {
3078 this.applyStylesToKeyframe();
3079 /** @type {?} */
3080 const preStyleProps = new Set();
3081 /** @type {?} */
3082 const postStyleProps = new Set();
3083 /** @type {?} */
3084 const isEmpty = this._keyframes.size === 1 && this.duration === 0;
3085 /** @type {?} */
3086 let finalKeyframes = [];
3087 this._keyframes.forEach((/**
3088 * @param {?} keyframe
3089 * @param {?} time
3090 * @return {?}
3091 */
3092 (keyframe, time) => {
3093 /** @type {?} */
3094 const finalKeyframe = copyStyles(keyframe, true);
3095 Object.keys(finalKeyframe).forEach((/**
3096 * @param {?} prop
3097 * @return {?}
3098 */
3099 prop => {
3100 /** @type {?} */
3101 const value = finalKeyframe[prop];
3102 if (value == ɵPRE_STYLE) {
3103 preStyleProps.add(prop);
3104 }
3105 else if (value == AUTO_STYLE) {
3106 postStyleProps.add(prop);
3107 }
3108 }));
3109 if (!isEmpty) {
3110 finalKeyframe['offset'] = time / this.duration;
3111 }
3112 finalKeyframes.push(finalKeyframe);
3113 }));
3114 /** @type {?} */
3115 const preProps = preStyleProps.size ? iteratorToArray(preStyleProps.values()) : [];
3116 /** @type {?} */
3117 const postProps = postStyleProps.size ? iteratorToArray(postStyleProps.values()) : [];
3118 // special case for a 0-second animation (which is designed just to place styles onscreen)
3119 if (isEmpty) {
3120 /** @type {?} */
3121 const kf0 = finalKeyframes[0];
3122 /** @type {?} */
3123 const kf1 = copyObj(kf0);
3124 kf0['offset'] = 0;
3125 kf1['offset'] = 1;
3126 finalKeyframes = [kf0, kf1];
3127 }
3128 return createTimelineInstruction(this.element, finalKeyframes, preProps, postProps, this.duration, this.startTime, this.easing, false);
3129 }
3130}
3131if (false) {
3132 /** @type {?} */
3133 TimelineBuilder.prototype.duration;
3134 /** @type {?} */
3135 TimelineBuilder.prototype.easing;
3136 /**
3137 * @type {?}
3138 * @private
3139 */
3140 TimelineBuilder.prototype._previousKeyframe;
3141 /**
3142 * @type {?}
3143 * @private
3144 */
3145 TimelineBuilder.prototype._currentKeyframe;
3146 /**
3147 * @type {?}
3148 * @private
3149 */
3150 TimelineBuilder.prototype._keyframes;
3151 /**
3152 * @type {?}
3153 * @private
3154 */
3155 TimelineBuilder.prototype._styleSummary;
3156 /**
3157 * @type {?}
3158 * @private
3159 */
3160 TimelineBuilder.prototype._localTimelineStyles;
3161 /**
3162 * @type {?}
3163 * @private
3164 */
3165 TimelineBuilder.prototype._globalTimelineStyles;
3166 /**
3167 * @type {?}
3168 * @private
3169 */
3170 TimelineBuilder.prototype._pendingStyles;
3171 /**
3172 * @type {?}
3173 * @private
3174 */
3175 TimelineBuilder.prototype._backFill;
3176 /**
3177 * @type {?}
3178 * @private
3179 */
3180 TimelineBuilder.prototype._currentEmptyStepKeyframe;
3181 /**
3182 * @type {?}
3183 * @private
3184 */
3185 TimelineBuilder.prototype._driver;
3186 /** @type {?} */
3187 TimelineBuilder.prototype.element;
3188 /** @type {?} */
3189 TimelineBuilder.prototype.startTime;
3190 /**
3191 * @type {?}
3192 * @private
3193 */
3194 TimelineBuilder.prototype._elementTimelineStylesLookup;
3195}
3196class SubTimelineBuilder extends TimelineBuilder {
3197 /**
3198 * @param {?} driver
3199 * @param {?} element
3200 * @param {?} keyframes
3201 * @param {?} preStyleProps
3202 * @param {?} postStyleProps
3203 * @param {?} timings
3204 * @param {?=} _stretchStartingKeyframe
3205 */
3206 constructor(driver, element, keyframes, preStyleProps, postStyleProps, timings, _stretchStartingKeyframe = false) {
3207 super(driver, element, timings.delay);
3208 this.element = element;
3209 this.keyframes = keyframes;
3210 this.preStyleProps = preStyleProps;
3211 this.postStyleProps = postStyleProps;
3212 this._stretchStartingKeyframe = _stretchStartingKeyframe;
3213 this.timings = { duration: timings.duration, delay: timings.delay, easing: timings.easing };
3214 }
3215 /**
3216 * @return {?}
3217 */
3218 containsAnimation() { return this.keyframes.length > 1; }
3219 /**
3220 * @return {?}
3221 */
3222 buildKeyframes() {
3223 /** @type {?} */
3224 let keyframes = this.keyframes;
3225 let { delay, duration, easing } = this.timings;
3226 if (this._stretchStartingKeyframe && delay) {
3227 /** @type {?} */
3228 const newKeyframes = [];
3229 /** @type {?} */
3230 const totalTime = duration + delay;
3231 /** @type {?} */
3232 const startingGap = delay / totalTime;
3233 // the original starting keyframe now starts once the delay is done
3234 /** @type {?} */
3235 const newFirstKeyframe = copyStyles(keyframes[0], false);
3236 newFirstKeyframe['offset'] = 0;
3237 newKeyframes.push(newFirstKeyframe);
3238 /** @type {?} */
3239 const oldFirstKeyframe = copyStyles(keyframes[0], false);
3240 oldFirstKeyframe['offset'] = roundOffset(startingGap);
3241 newKeyframes.push(oldFirstKeyframe);
3242 /*
3243 When the keyframe is stretched then it means that the delay before the animation
3244 starts is gone. Instead the first keyframe is placed at the start of the animation
3245 and it is then copied to where it starts when the original delay is over. This basically
3246 means nothing animates during that delay, but the styles are still renderered. For this
3247 to work the original offset values that exist in the original keyframes must be "warped"
3248 so that they can take the new keyframe + delay into account.
3249
3250 delay=1000, duration=1000, keyframes = 0 .5 1
3251
3252 turns into
3253
3254 delay=0, duration=2000, keyframes = 0 .33 .66 1
3255 */
3256 // offsets between 1 ... n -1 are all warped by the keyframe stretch
3257 /** @type {?} */
3258 const limit = keyframes.length - 1;
3259 for (let i = 1; i <= limit; i++) {
3260 /** @type {?} */
3261 let kf = copyStyles(keyframes[i], false);
3262 /** @type {?} */
3263 const oldOffset = (/** @type {?} */ (kf['offset']));
3264 /** @type {?} */
3265 const timeAtKeyframe = delay + oldOffset * duration;
3266 kf['offset'] = roundOffset(timeAtKeyframe / totalTime);
3267 newKeyframes.push(kf);
3268 }
3269 // the new starting keyframe should be added at the start
3270 duration = totalTime;
3271 delay = 0;
3272 easing = '';
3273 keyframes = newKeyframes;
3274 }
3275 return createTimelineInstruction(this.element, keyframes, this.preStyleProps, this.postStyleProps, duration, delay, easing, true);
3276 }
3277}
3278if (false) {
3279 /** @type {?} */
3280 SubTimelineBuilder.prototype.timings;
3281 /** @type {?} */
3282 SubTimelineBuilder.prototype.element;
3283 /** @type {?} */
3284 SubTimelineBuilder.prototype.keyframes;
3285 /** @type {?} */
3286 SubTimelineBuilder.prototype.preStyleProps;
3287 /** @type {?} */
3288 SubTimelineBuilder.prototype.postStyleProps;
3289 /**
3290 * @type {?}
3291 * @private
3292 */
3293 SubTimelineBuilder.prototype._stretchStartingKeyframe;
3294}
3295/**
3296 * @param {?} offset
3297 * @param {?=} decimalPoints
3298 * @return {?}
3299 */
3300function roundOffset(offset, decimalPoints = 3) {
3301 /** @type {?} */
3302 const mult = Math.pow(10, decimalPoints - 1);
3303 return Math.round(offset * mult) / mult;
3304}
3305/**
3306 * @param {?} input
3307 * @param {?} allStyles
3308 * @return {?}
3309 */
3310function flattenStyles(input, allStyles) {
3311 /** @type {?} */
3312 const styles = {};
3313 /** @type {?} */
3314 let allProperties;
3315 input.forEach((/**
3316 * @param {?} token
3317 * @return {?}
3318 */
3319 token => {
3320 if (token === '*') {
3321 allProperties = allProperties || Object.keys(allStyles);
3322 allProperties.forEach((/**
3323 * @param {?} prop
3324 * @return {?}
3325 */
3326 prop => { styles[prop] = AUTO_STYLE; }));
3327 }
3328 else {
3329 copyStyles((/** @type {?} */ (token)), false, styles);
3330 }
3331 }));
3332 return styles;
3333}
3334
3335/**
3336 * @fileoverview added by tsickle
3337 * Generated from: packages/animations/browser/src/dsl/animation.ts
3338 * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
3339 */
3340class Animation {
3341 /**
3342 * @param {?} _driver
3343 * @param {?} input
3344 */
3345 constructor(_driver, input) {
3346 this._driver = _driver;
3347 /** @type {?} */
3348 const errors = [];
3349 /** @type {?} */
3350 const ast = buildAnimationAst(_driver, input, errors);
3351 if (errors.length) {
3352 /** @type {?} */
3353 const errorMessage = `animation validation failed:\n${errors.join("\n")}`;
3354 throw new Error(errorMessage);
3355 }
3356 this._animationAst = ast;
3357 }
3358 /**
3359 * @param {?} element
3360 * @param {?} startingStyles
3361 * @param {?} destinationStyles
3362 * @param {?} options
3363 * @param {?=} subInstructions
3364 * @return {?}
3365 */
3366 buildTimelines(element, startingStyles, destinationStyles, options, subInstructions) {
3367 /** @type {?} */
3368 const start = Array.isArray(startingStyles) ? normalizeStyles(startingStyles) :
3369 (/** @type {?} */ (startingStyles));
3370 /** @type {?} */
3371 const dest = Array.isArray(destinationStyles) ? normalizeStyles(destinationStyles) :
3372 (/** @type {?} */ (destinationStyles));
3373 /** @type {?} */
3374 const errors = [];
3375 subInstructions = subInstructions || new ElementInstructionMap();
3376 /** @type {?} */
3377 const result = buildAnimationTimelines(this._driver, element, this._animationAst, ENTER_CLASSNAME, LEAVE_CLASSNAME, start, dest, options, subInstructions, errors);
3378 if (errors.length) {
3379 /** @type {?} */
3380 const errorMessage = `animation building failed:\n${errors.join("\n")}`;
3381 throw new Error(errorMessage);
3382 }
3383 return result;
3384 }
3385}
3386if (false) {
3387 /**
3388 * @type {?}
3389 * @private
3390 */
3391 Animation.prototype._animationAst;
3392 /**
3393 * @type {?}
3394 * @private
3395 */
3396 Animation.prototype._driver;
3397}
3398
3399/**
3400 * @fileoverview added by tsickle
3401 * Generated from: packages/animations/browser/src/dsl/style_normalization/animation_style_normalizer.ts
3402 * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
3403 */
3404/**
3405 * @license
3406 * Copyright Google Inc. All Rights Reserved.
3407 *
3408 * Use of this source code is governed by an MIT-style license that can be
3409 * found in the LICENSE file at https://angular.io/license
3410 */
3411/**
3412 * \@publicApi
3413 * @abstract
3414 */
3415class AnimationStyleNormalizer {
3416}
3417if (false) {
3418 /**
3419 * @abstract
3420 * @param {?} propertyName
3421 * @param {?} errors
3422 * @return {?}
3423 */
3424 AnimationStyleNormalizer.prototype.normalizePropertyName = function (propertyName, errors) { };
3425 /**
3426 * @abstract
3427 * @param {?} userProvidedProperty
3428 * @param {?} normalizedProperty
3429 * @param {?} value
3430 * @param {?} errors
3431 * @return {?}
3432 */
3433 AnimationStyleNormalizer.prototype.normalizeStyleValue = function (userProvidedProperty, normalizedProperty, value, errors) { };
3434}
3435/**
3436 * \@publicApi
3437 */
3438class NoopAnimationStyleNormalizer {
3439 /**
3440 * @param {?} propertyName
3441 * @param {?} errors
3442 * @return {?}
3443 */
3444 normalizePropertyName(propertyName, errors) { return propertyName; }
3445 /**
3446 * @param {?} userProvidedProperty
3447 * @param {?} normalizedProperty
3448 * @param {?} value
3449 * @param {?} errors
3450 * @return {?}
3451 */
3452 normalizeStyleValue(userProvidedProperty, normalizedProperty, value, errors) {
3453 return (/** @type {?} */ (value));
3454 }
3455}
3456
3457/**
3458 * @fileoverview added by tsickle
3459 * Generated from: packages/animations/browser/src/dsl/style_normalization/web_animations_style_normalizer.ts
3460 * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
3461 */
3462class WebAnimationsStyleNormalizer extends AnimationStyleNormalizer {
3463 /**
3464 * @param {?} propertyName
3465 * @param {?} errors
3466 * @return {?}
3467 */
3468 normalizePropertyName(propertyName, errors) {
3469 return dashCaseToCamelCase(propertyName);
3470 }
3471 /**
3472 * @param {?} userProvidedProperty
3473 * @param {?} normalizedProperty
3474 * @param {?} value
3475 * @param {?} errors
3476 * @return {?}
3477 */
3478 normalizeStyleValue(userProvidedProperty, normalizedProperty, value, errors) {
3479 /** @type {?} */
3480 let unit = '';
3481 /** @type {?} */
3482 const strVal = value.toString().trim();
3483 if (DIMENSIONAL_PROP_MAP[normalizedProperty] && value !== 0 && value !== '0') {
3484 if (typeof value === 'number') {
3485 unit = 'px';
3486 }
3487 else {
3488 /** @type {?} */
3489 const valAndSuffixMatch = value.match(/^[+-]?[\d\.]+([a-z]*)$/);
3490 if (valAndSuffixMatch && valAndSuffixMatch[1].length == 0) {
3491 errors.push(`Please provide a CSS unit value for ${userProvidedProperty}:${value}`);
3492 }
3493 }
3494 }
3495 return strVal + unit;
3496 }
3497}
3498const ɵ0$1 = /**
3499 * @return {?}
3500 */
3501() => 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'
3502 .split(','));
3503/** @type {?} */
3504const DIMENSIONAL_PROP_MAP = ((ɵ0$1))();
3505/**
3506 * @param {?} keys
3507 * @return {?}
3508 */
3509function makeBooleanMap(keys) {
3510 /** @type {?} */
3511 const map = {};
3512 keys.forEach((/**
3513 * @param {?} key
3514 * @return {?}
3515 */
3516 key => map[key] = true));
3517 return map;
3518}
3519
3520/**
3521 * @fileoverview added by tsickle
3522 * Generated from: packages/animations/browser/src/dsl/animation_transition_instruction.ts
3523 * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
3524 */
3525/**
3526 * @record
3527 */
3528function AnimationTransitionInstruction() { }
3529if (false) {
3530 /** @type {?} */
3531 AnimationTransitionInstruction.prototype.element;
3532 /** @type {?} */
3533 AnimationTransitionInstruction.prototype.triggerName;
3534 /** @type {?} */
3535 AnimationTransitionInstruction.prototype.isRemovalTransition;
3536 /** @type {?} */
3537 AnimationTransitionInstruction.prototype.fromState;
3538 /** @type {?} */
3539 AnimationTransitionInstruction.prototype.fromStyles;
3540 /** @type {?} */
3541 AnimationTransitionInstruction.prototype.toState;
3542 /** @type {?} */
3543 AnimationTransitionInstruction.prototype.toStyles;
3544 /** @type {?} */
3545 AnimationTransitionInstruction.prototype.timelines;
3546 /** @type {?} */
3547 AnimationTransitionInstruction.prototype.queriedElements;
3548 /** @type {?} */
3549 AnimationTransitionInstruction.prototype.preStyleProps;
3550 /** @type {?} */
3551 AnimationTransitionInstruction.prototype.postStyleProps;
3552 /** @type {?} */
3553 AnimationTransitionInstruction.prototype.totalTime;
3554 /** @type {?|undefined} */
3555 AnimationTransitionInstruction.prototype.errors;
3556}
3557/**
3558 * @param {?} element
3559 * @param {?} triggerName
3560 * @param {?} fromState
3561 * @param {?} toState
3562 * @param {?} isRemovalTransition
3563 * @param {?} fromStyles
3564 * @param {?} toStyles
3565 * @param {?} timelines
3566 * @param {?} queriedElements
3567 * @param {?} preStyleProps
3568 * @param {?} postStyleProps
3569 * @param {?} totalTime
3570 * @param {?=} errors
3571 * @return {?}
3572 */
3573function createTransitionInstruction(element, triggerName, fromState, toState, isRemovalTransition, fromStyles, toStyles, timelines, queriedElements, preStyleProps, postStyleProps, totalTime, errors) {
3574 return {
3575 type: 0 /* TransitionAnimation */,
3576 element,
3577 triggerName,
3578 isRemovalTransition,
3579 fromState,
3580 fromStyles,
3581 toState,
3582 toStyles,
3583 timelines,
3584 queriedElements,
3585 preStyleProps,
3586 postStyleProps,
3587 totalTime,
3588 errors
3589 };
3590}
3591
3592/**
3593 * @fileoverview added by tsickle
3594 * Generated from: packages/animations/browser/src/dsl/animation_transition_factory.ts
3595 * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
3596 */
3597/** @type {?} */
3598const EMPTY_OBJECT = {};
3599class AnimationTransitionFactory {
3600 /**
3601 * @param {?} _triggerName
3602 * @param {?} ast
3603 * @param {?} _stateStyles
3604 */
3605 constructor(_triggerName, ast, _stateStyles) {
3606 this._triggerName = _triggerName;
3607 this.ast = ast;
3608 this._stateStyles = _stateStyles;
3609 }
3610 /**
3611 * @param {?} currentState
3612 * @param {?} nextState
3613 * @param {?} element
3614 * @param {?} params
3615 * @return {?}
3616 */
3617 match(currentState, nextState, element, params) {
3618 return oneOrMoreTransitionsMatch(this.ast.matchers, currentState, nextState, element, params);
3619 }
3620 /**
3621 * @param {?} stateName
3622 * @param {?} params
3623 * @param {?} errors
3624 * @return {?}
3625 */
3626 buildStyles(stateName, params, errors) {
3627 /** @type {?} */
3628 const backupStateStyler = this._stateStyles['*'];
3629 /** @type {?} */
3630 const stateStyler = this._stateStyles[stateName];
3631 /** @type {?} */
3632 const backupStyles = backupStateStyler ? backupStateStyler.buildStyles(params, errors) : {};
3633 return stateStyler ? stateStyler.buildStyles(params, errors) : backupStyles;
3634 }
3635 /**
3636 * @param {?} driver
3637 * @param {?} element
3638 * @param {?} currentState
3639 * @param {?} nextState
3640 * @param {?} enterClassName
3641 * @param {?} leaveClassName
3642 * @param {?=} currentOptions
3643 * @param {?=} nextOptions
3644 * @param {?=} subInstructions
3645 * @param {?=} skipAstBuild
3646 * @return {?}
3647 */
3648 build(driver, element, currentState, nextState, enterClassName, leaveClassName, currentOptions, nextOptions, subInstructions, skipAstBuild) {
3649 /** @type {?} */
3650 const errors = [];
3651 /** @type {?} */
3652 const transitionAnimationParams = this.ast.options && this.ast.options.params || EMPTY_OBJECT;
3653 /** @type {?} */
3654 const currentAnimationParams = currentOptions && currentOptions.params || EMPTY_OBJECT;
3655 /** @type {?} */
3656 const currentStateStyles = this.buildStyles(currentState, currentAnimationParams, errors);
3657 /** @type {?} */
3658 const nextAnimationParams = nextOptions && nextOptions.params || EMPTY_OBJECT;
3659 /** @type {?} */
3660 const nextStateStyles = this.buildStyles(nextState, nextAnimationParams, errors);
3661 /** @type {?} */
3662 const queriedElements = new Set();
3663 /** @type {?} */
3664 const preStyleMap = new Map();
3665 /** @type {?} */
3666 const postStyleMap = new Map();
3667 /** @type {?} */
3668 const isRemoval = nextState === 'void';
3669 /** @type {?} */
3670 const animationOptions = { params: Object.assign(Object.assign({}, transitionAnimationParams), nextAnimationParams) };
3671 /** @type {?} */
3672 const timelines = skipAstBuild ? [] : buildAnimationTimelines(driver, element, this.ast.animation, enterClassName, leaveClassName, currentStateStyles, nextStateStyles, animationOptions, subInstructions, errors);
3673 /** @type {?} */
3674 let totalTime = 0;
3675 timelines.forEach((/**
3676 * @param {?} tl
3677 * @return {?}
3678 */
3679 tl => { totalTime = Math.max(tl.duration + tl.delay, totalTime); }));
3680 if (errors.length) {
3681 return createTransitionInstruction(element, this._triggerName, currentState, nextState, isRemoval, currentStateStyles, nextStateStyles, [], [], preStyleMap, postStyleMap, totalTime, errors);
3682 }
3683 timelines.forEach((/**
3684 * @param {?} tl
3685 * @return {?}
3686 */
3687 tl => {
3688 /** @type {?} */
3689 const elm = tl.element;
3690 /** @type {?} */
3691 const preProps = getOrSetAsInMap(preStyleMap, elm, {});
3692 tl.preStyleProps.forEach((/**
3693 * @param {?} prop
3694 * @return {?}
3695 */
3696 prop => preProps[prop] = true));
3697 /** @type {?} */
3698 const postProps = getOrSetAsInMap(postStyleMap, elm, {});
3699 tl.postStyleProps.forEach((/**
3700 * @param {?} prop
3701 * @return {?}
3702 */
3703 prop => postProps[prop] = true));
3704 if (elm !== element) {
3705 queriedElements.add(elm);
3706 }
3707 }));
3708 /** @type {?} */
3709 const queriedElementsList = iteratorToArray(queriedElements.values());
3710 return createTransitionInstruction(element, this._triggerName, currentState, nextState, isRemoval, currentStateStyles, nextStateStyles, timelines, queriedElementsList, preStyleMap, postStyleMap, totalTime);
3711 }
3712}
3713if (false) {
3714 /**
3715 * @type {?}
3716 * @private
3717 */
3718 AnimationTransitionFactory.prototype._triggerName;
3719 /** @type {?} */
3720 AnimationTransitionFactory.prototype.ast;
3721 /**
3722 * @type {?}
3723 * @private
3724 */
3725 AnimationTransitionFactory.prototype._stateStyles;
3726}
3727/**
3728 * @param {?} matchFns
3729 * @param {?} currentState
3730 * @param {?} nextState
3731 * @param {?} element
3732 * @param {?} params
3733 * @return {?}
3734 */
3735function oneOrMoreTransitionsMatch(matchFns, currentState, nextState, element, params) {
3736 return matchFns.some((/**
3737 * @param {?} fn
3738 * @return {?}
3739 */
3740 fn => fn(currentState, nextState, element, params)));
3741}
3742class AnimationStateStyles {
3743 /**
3744 * @param {?} styles
3745 * @param {?} defaultParams
3746 */
3747 constructor(styles, defaultParams) {
3748 this.styles = styles;
3749 this.defaultParams = defaultParams;
3750 }
3751 /**
3752 * @param {?} params
3753 * @param {?} errors
3754 * @return {?}
3755 */
3756 buildStyles(params, errors) {
3757 /** @type {?} */
3758 const finalStyles = {};
3759 /** @type {?} */
3760 const combinedParams = copyObj(this.defaultParams);
3761 Object.keys(params).forEach((/**
3762 * @param {?} key
3763 * @return {?}
3764 */
3765 key => {
3766 /** @type {?} */
3767 const value = params[key];
3768 if (value != null) {
3769 combinedParams[key] = value;
3770 }
3771 }));
3772 this.styles.styles.forEach((/**
3773 * @param {?} value
3774 * @return {?}
3775 */
3776 value => {
3777 if (typeof value !== 'string') {
3778 /** @type {?} */
3779 const styleObj = (/** @type {?} */ (value));
3780 Object.keys(styleObj).forEach((/**
3781 * @param {?} prop
3782 * @return {?}
3783 */
3784 prop => {
3785 /** @type {?} */
3786 let val = styleObj[prop];
3787 if (val.length > 1) {
3788 val = interpolateParams(val, combinedParams, errors);
3789 }
3790 finalStyles[prop] = val;
3791 }));
3792 }
3793 }));
3794 return finalStyles;
3795 }
3796}
3797if (false) {
3798 /**
3799 * @type {?}
3800 * @private
3801 */
3802 AnimationStateStyles.prototype.styles;
3803 /**
3804 * @type {?}
3805 * @private
3806 */
3807 AnimationStateStyles.prototype.defaultParams;
3808}
3809
3810/**
3811 * @fileoverview added by tsickle
3812 * Generated from: packages/animations/browser/src/dsl/animation_trigger.ts
3813 * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
3814 */
3815/**
3816 * \@publicApi
3817 * @param {?} name
3818 * @param {?} ast
3819 * @return {?}
3820 */
3821function buildTrigger(name, ast) {
3822 return new AnimationTrigger(name, ast);
3823}
3824/**
3825 * \@publicApi
3826 */
3827class AnimationTrigger {
3828 /**
3829 * @param {?} name
3830 * @param {?} ast
3831 */
3832 constructor(name, ast) {
3833 this.name = name;
3834 this.ast = ast;
3835 this.transitionFactories = [];
3836 this.states = {};
3837 ast.states.forEach((/**
3838 * @param {?} ast
3839 * @return {?}
3840 */
3841 ast => {
3842 /** @type {?} */
3843 const defaultParams = (ast.options && ast.options.params) || {};
3844 this.states[ast.name] = new AnimationStateStyles(ast.style, defaultParams);
3845 }));
3846 balanceProperties(this.states, 'true', '1');
3847 balanceProperties(this.states, 'false', '0');
3848 ast.transitions.forEach((/**
3849 * @param {?} ast
3850 * @return {?}
3851 */
3852 ast => {
3853 this.transitionFactories.push(new AnimationTransitionFactory(name, ast, this.states));
3854 }));
3855 this.fallbackTransition = createFallbackTransition(name, this.states);
3856 }
3857 /**
3858 * @return {?}
3859 */
3860 get containsQueries() { return this.ast.queryCount > 0; }
3861 /**
3862 * @param {?} currentState
3863 * @param {?} nextState
3864 * @param {?} element
3865 * @param {?} params
3866 * @return {?}
3867 */
3868 matchTransition(currentState, nextState, element, params) {
3869 /** @type {?} */
3870 const entry = this.transitionFactories.find((/**
3871 * @param {?} f
3872 * @return {?}
3873 */
3874 f => f.match(currentState, nextState, element, params)));
3875 return entry || null;
3876 }
3877 /**
3878 * @param {?} currentState
3879 * @param {?} params
3880 * @param {?} errors
3881 * @return {?}
3882 */
3883 matchStyles(currentState, params, errors) {
3884 return this.fallbackTransition.buildStyles(currentState, params, errors);
3885 }
3886}
3887if (false) {
3888 /** @type {?} */
3889 AnimationTrigger.prototype.transitionFactories;
3890 /** @type {?} */
3891 AnimationTrigger.prototype.fallbackTransition;
3892 /** @type {?} */
3893 AnimationTrigger.prototype.states;
3894 /** @type {?} */
3895 AnimationTrigger.prototype.name;
3896 /** @type {?} */
3897 AnimationTrigger.prototype.ast;
3898}
3899/**
3900 * @param {?} triggerName
3901 * @param {?} states
3902 * @return {?}
3903 */
3904function createFallbackTransition(triggerName, states) {
3905 /** @type {?} */
3906 const matchers = [(/**
3907 * @param {?} fromState
3908 * @param {?} toState
3909 * @return {?}
3910 */
3911 (fromState, toState) => true)];
3912 /** @type {?} */
3913 const animation = { type: 2 /* Sequence */, steps: [], options: null };
3914 /** @type {?} */
3915 const transition = {
3916 type: 1 /* Transition */,
3917 animation,
3918 matchers,
3919 options: null,
3920 queryCount: 0,
3921 depCount: 0
3922 };
3923 return new AnimationTransitionFactory(triggerName, transition, states);
3924}
3925/**
3926 * @param {?} obj
3927 * @param {?} key1
3928 * @param {?} key2
3929 * @return {?}
3930 */
3931function balanceProperties(obj, key1, key2) {
3932 if (obj.hasOwnProperty(key1)) {
3933 if (!obj.hasOwnProperty(key2)) {
3934 obj[key2] = obj[key1];
3935 }
3936 }
3937 else if (obj.hasOwnProperty(key2)) {
3938 obj[key1] = obj[key2];
3939 }
3940}
3941
3942/**
3943 * @fileoverview added by tsickle
3944 * Generated from: packages/animations/browser/src/render/timeline_animation_engine.ts
3945 * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
3946 */
3947/** @type {?} */
3948const EMPTY_INSTRUCTION_MAP = new ElementInstructionMap();
3949class TimelineAnimationEngine {
3950 /**
3951 * @param {?} bodyNode
3952 * @param {?} _driver
3953 * @param {?} _normalizer
3954 */
3955 constructor(bodyNode, _driver, _normalizer) {
3956 this.bodyNode = bodyNode;
3957 this._driver = _driver;
3958 this._normalizer = _normalizer;
3959 this._animations = {};
3960 this._playersById = {};
3961 this.players = [];
3962 }
3963 /**
3964 * @param {?} id
3965 * @param {?} metadata
3966 * @return {?}
3967 */
3968 register(id, metadata) {
3969 /** @type {?} */
3970 const errors = [];
3971 /** @type {?} */
3972 const ast = buildAnimationAst(this._driver, metadata, errors);
3973 if (errors.length) {
3974 throw new Error(`Unable to build the animation due to the following errors: ${errors.join("\n")}`);
3975 }
3976 else {
3977 this._animations[id] = ast;
3978 }
3979 }
3980 /**
3981 * @private
3982 * @param {?} i
3983 * @param {?} preStyles
3984 * @param {?=} postStyles
3985 * @return {?}
3986 */
3987 _buildPlayer(i, preStyles, postStyles) {
3988 /** @type {?} */
3989 const element = i.element;
3990 /** @type {?} */
3991 const keyframes = normalizeKeyframes(this._driver, this._normalizer, element, i.keyframes, preStyles, postStyles);
3992 return this._driver.animate(element, keyframes, i.duration, i.delay, i.easing, [], true);
3993 }
3994 /**
3995 * @param {?} id
3996 * @param {?} element
3997 * @param {?=} options
3998 * @return {?}
3999 */
4000 create(id, element, options = {}) {
4001 /** @type {?} */
4002 const errors = [];
4003 /** @type {?} */
4004 const ast = this._animations[id];
4005 /** @type {?} */
4006 let instructions;
4007 /** @type {?} */
4008 const autoStylesMap = new Map();
4009 if (ast) {
4010 instructions = buildAnimationTimelines(this._driver, element, ast, ENTER_CLASSNAME, LEAVE_CLASSNAME, {}, {}, options, EMPTY_INSTRUCTION_MAP, errors);
4011 instructions.forEach((/**
4012 * @param {?} inst
4013 * @return {?}
4014 */
4015 inst => {
4016 /** @type {?} */
4017 const styles = getOrSetAsInMap(autoStylesMap, inst.element, {});
4018 inst.postStyleProps.forEach((/**
4019 * @param {?} prop
4020 * @return {?}
4021 */
4022 prop => styles[prop] = null));
4023 }));
4024 }
4025 else {
4026 errors.push('The requested animation doesn\'t exist or has already been destroyed');
4027 instructions = [];
4028 }
4029 if (errors.length) {
4030 throw new Error(`Unable to create the animation due to the following errors: ${errors.join("\n")}`);
4031 }
4032 autoStylesMap.forEach((/**
4033 * @param {?} styles
4034 * @param {?} element
4035 * @return {?}
4036 */
4037 (styles, element) => {
4038 Object.keys(styles).forEach((/**
4039 * @param {?} prop
4040 * @return {?}
4041 */
4042 prop => { styles[prop] = this._driver.computeStyle(element, prop, AUTO_STYLE); }));
4043 }));
4044 /** @type {?} */
4045 const players = instructions.map((/**
4046 * @param {?} i
4047 * @return {?}
4048 */
4049 i => {
4050 /** @type {?} */
4051 const styles = autoStylesMap.get(i.element);
4052 return this._buildPlayer(i, {}, styles);
4053 }));
4054 /** @type {?} */
4055 const player = optimizeGroupPlayer(players);
4056 this._playersById[id] = player;
4057 player.onDestroy((/**
4058 * @return {?}
4059 */
4060 () => this.destroy(id)));
4061 this.players.push(player);
4062 return player;
4063 }
4064 /**
4065 * @param {?} id
4066 * @return {?}
4067 */
4068 destroy(id) {
4069 /** @type {?} */
4070 const player = this._getPlayer(id);
4071 player.destroy();
4072 delete this._playersById[id];
4073 /** @type {?} */
4074 const index = this.players.indexOf(player);
4075 if (index >= 0) {
4076 this.players.splice(index, 1);
4077 }
4078 }
4079 /**
4080 * @private
4081 * @param {?} id
4082 * @return {?}
4083 */
4084 _getPlayer(id) {
4085 /** @type {?} */
4086 const player = this._playersById[id];
4087 if (!player) {
4088 throw new Error(`Unable to find the timeline player referenced by ${id}`);
4089 }
4090 return player;
4091 }
4092 /**
4093 * @param {?} id
4094 * @param {?} element
4095 * @param {?} eventName
4096 * @param {?} callback
4097 * @return {?}
4098 */
4099 listen(id, element, eventName, callback) {
4100 // triggerName, fromState, toState are all ignored for timeline animations
4101 /** @type {?} */
4102 const baseEvent = makeAnimationEvent(element, '', '', '');
4103 listenOnPlayer(this._getPlayer(id), eventName, baseEvent, callback);
4104 return (/**
4105 * @return {?}
4106 */
4107 () => { });
4108 }
4109 /**
4110 * @param {?} id
4111 * @param {?} element
4112 * @param {?} command
4113 * @param {?} args
4114 * @return {?}
4115 */
4116 command(id, element, command, args) {
4117 if (command == 'register') {
4118 this.register(id, (/** @type {?} */ (args[0])));
4119 return;
4120 }
4121 if (command == 'create') {
4122 /** @type {?} */
4123 const options = (/** @type {?} */ ((args[0] || {})));
4124 this.create(id, element, options);
4125 return;
4126 }
4127 /** @type {?} */
4128 const player = this._getPlayer(id);
4129 switch (command) {
4130 case 'play':
4131 player.play();
4132 break;
4133 case 'pause':
4134 player.pause();
4135 break;
4136 case 'reset':
4137 player.reset();
4138 break;
4139 case 'restart':
4140 player.restart();
4141 break;
4142 case 'finish':
4143 player.finish();
4144 break;
4145 case 'init':
4146 player.init();
4147 break;
4148 case 'setPosition':
4149 player.setPosition(parseFloat((/** @type {?} */ (args[0]))));
4150 break;
4151 case 'destroy':
4152 this.destroy(id);
4153 break;
4154 }
4155 }
4156}
4157if (false) {
4158 /**
4159 * @type {?}
4160 * @private
4161 */
4162 TimelineAnimationEngine.prototype._animations;
4163 /**
4164 * @type {?}
4165 * @private
4166 */
4167 TimelineAnimationEngine.prototype._playersById;
4168 /** @type {?} */
4169 TimelineAnimationEngine.prototype.players;
4170 /** @type {?} */
4171 TimelineAnimationEngine.prototype.bodyNode;
4172 /**
4173 * @type {?}
4174 * @private
4175 */
4176 TimelineAnimationEngine.prototype._driver;
4177 /**
4178 * @type {?}
4179 * @private
4180 */
4181 TimelineAnimationEngine.prototype._normalizer;
4182}
4183
4184/**
4185 * @fileoverview added by tsickle
4186 * Generated from: packages/animations/browser/src/render/transition_animation_engine.ts
4187 * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
4188 */
4189/** @type {?} */
4190const QUEUED_CLASSNAME = 'ng-animate-queued';
4191/** @type {?} */
4192const QUEUED_SELECTOR = '.ng-animate-queued';
4193/** @type {?} */
4194const DISABLED_CLASSNAME = 'ng-animate-disabled';
4195/** @type {?} */
4196const DISABLED_SELECTOR = '.ng-animate-disabled';
4197/** @type {?} */
4198const STAR_CLASSNAME = 'ng-star-inserted';
4199/** @type {?} */
4200const STAR_SELECTOR = '.ng-star-inserted';
4201/** @type {?} */
4202const EMPTY_PLAYER_ARRAY = [];
4203/** @type {?} */
4204const NULL_REMOVAL_STATE = {
4205 namespaceId: '',
4206 setForRemoval: false,
4207 setForMove: false,
4208 hasAnimation: false,
4209 removedBeforeQueried: false
4210};
4211/** @type {?} */
4212const NULL_REMOVED_QUERIED_STATE = {
4213 namespaceId: '',
4214 setForMove: false,
4215 setForRemoval: false,
4216 hasAnimation: false,
4217 removedBeforeQueried: true
4218};
4219/**
4220 * @record
4221 */
4222function TriggerListener() { }
4223if (false) {
4224 /** @type {?} */
4225 TriggerListener.prototype.name;
4226 /** @type {?} */
4227 TriggerListener.prototype.phase;
4228 /** @type {?} */
4229 TriggerListener.prototype.callback;
4230}
4231/**
4232 * @record
4233 */
4234function QueueInstruction() { }
4235if (false) {
4236 /** @type {?} */
4237 QueueInstruction.prototype.element;
4238 /** @type {?} */
4239 QueueInstruction.prototype.triggerName;
4240 /** @type {?} */
4241 QueueInstruction.prototype.fromState;
4242 /** @type {?} */
4243 QueueInstruction.prototype.toState;
4244 /** @type {?} */
4245 QueueInstruction.prototype.transition;
4246 /** @type {?} */
4247 QueueInstruction.prototype.player;
4248 /** @type {?} */
4249 QueueInstruction.prototype.isFallbackTransition;
4250}
4251/** @type {?} */
4252const REMOVAL_FLAG = '__ng_removed';
4253/**
4254 * @record
4255 */
4256function ElementAnimationState() { }
4257if (false) {
4258 /** @type {?} */
4259 ElementAnimationState.prototype.setForRemoval;
4260 /** @type {?} */
4261 ElementAnimationState.prototype.setForMove;
4262 /** @type {?} */
4263 ElementAnimationState.prototype.hasAnimation;
4264 /** @type {?} */
4265 ElementAnimationState.prototype.namespaceId;
4266 /** @type {?} */
4267 ElementAnimationState.prototype.removedBeforeQueried;
4268}
4269class StateValue {
4270 /**
4271 * @param {?} input
4272 * @param {?=} namespaceId
4273 */
4274 constructor(input, namespaceId = '') {
4275 this.namespaceId = namespaceId;
4276 /** @type {?} */
4277 const isObj = input && input.hasOwnProperty('value');
4278 /** @type {?} */
4279 const value = isObj ? input['value'] : input;
4280 this.value = normalizeTriggerValue(value);
4281 if (isObj) {
4282 /** @type {?} */
4283 const options = copyObj((/** @type {?} */ (input)));
4284 delete options['value'];
4285 this.options = (/** @type {?} */ (options));
4286 }
4287 else {
4288 this.options = {};
4289 }
4290 if (!this.options.params) {
4291 this.options.params = {};
4292 }
4293 }
4294 /**
4295 * @return {?}
4296 */
4297 get params() { return (/** @type {?} */ (this.options.params)); }
4298 /**
4299 * @param {?} options
4300 * @return {?}
4301 */
4302 absorbOptions(options) {
4303 /** @type {?} */
4304 const newParams = options.params;
4305 if (newParams) {
4306 /** @type {?} */
4307 const oldParams = (/** @type {?} */ (this.options.params));
4308 Object.keys(newParams).forEach((/**
4309 * @param {?} prop
4310 * @return {?}
4311 */
4312 prop => {
4313 if (oldParams[prop] == null) {
4314 oldParams[prop] = newParams[prop];
4315 }
4316 }));
4317 }
4318 }
4319}
4320if (false) {
4321 /** @type {?} */
4322 StateValue.prototype.value;
4323 /** @type {?} */
4324 StateValue.prototype.options;
4325 /** @type {?} */
4326 StateValue.prototype.namespaceId;
4327}
4328/** @type {?} */
4329const VOID_VALUE = 'void';
4330/** @type {?} */
4331const DEFAULT_STATE_VALUE = new StateValue(VOID_VALUE);
4332class AnimationTransitionNamespace {
4333 /**
4334 * @param {?} id
4335 * @param {?} hostElement
4336 * @param {?} _engine
4337 */
4338 constructor(id, hostElement, _engine) {
4339 this.id = id;
4340 this.hostElement = hostElement;
4341 this._engine = _engine;
4342 this.players = [];
4343 this._triggers = {};
4344 this._queue = [];
4345 this._elementListeners = new Map();
4346 this._hostClassName = 'ng-tns-' + id;
4347 addClass(hostElement, this._hostClassName);
4348 }
4349 /**
4350 * @param {?} element
4351 * @param {?} name
4352 * @param {?} phase
4353 * @param {?} callback
4354 * @return {?}
4355 */
4356 listen(element, name, phase, callback) {
4357 if (!this._triggers.hasOwnProperty(name)) {
4358 throw new Error(`Unable to listen on the animation trigger event "${phase}" because the animation trigger "${name}" doesn\'t exist!`);
4359 }
4360 if (phase == null || phase.length == 0) {
4361 throw new Error(`Unable to listen on the animation trigger "${name}" because the provided event is undefined!`);
4362 }
4363 if (!isTriggerEventValid(phase)) {
4364 throw new Error(`The provided animation trigger event "${phase}" for the animation trigger "${name}" is not supported!`);
4365 }
4366 /** @type {?} */
4367 const listeners = getOrSetAsInMap(this._elementListeners, element, []);
4368 /** @type {?} */
4369 const data = { name, phase, callback };
4370 listeners.push(data);
4371 /** @type {?} */
4372 const triggersWithStates = getOrSetAsInMap(this._engine.statesByElement, element, {});
4373 if (!triggersWithStates.hasOwnProperty(name)) {
4374 addClass(element, NG_TRIGGER_CLASSNAME);
4375 addClass(element, NG_TRIGGER_CLASSNAME + '-' + name);
4376 triggersWithStates[name] = DEFAULT_STATE_VALUE;
4377 }
4378 return (/**
4379 * @return {?}
4380 */
4381 () => {
4382 // the event listener is removed AFTER the flush has occurred such
4383 // that leave animations callbacks can fire (otherwise if the node
4384 // is removed in between then the listeners would be deregistered)
4385 this._engine.afterFlush((/**
4386 * @return {?}
4387 */
4388 () => {
4389 /** @type {?} */
4390 const index = listeners.indexOf(data);
4391 if (index >= 0) {
4392 listeners.splice(index, 1);
4393 }
4394 if (!this._triggers[name]) {
4395 delete triggersWithStates[name];
4396 }
4397 }));
4398 });
4399 }
4400 /**
4401 * @param {?} name
4402 * @param {?} ast
4403 * @return {?}
4404 */
4405 register(name, ast) {
4406 if (this._triggers[name]) {
4407 // throw
4408 return false;
4409 }
4410 else {
4411 this._triggers[name] = ast;
4412 return true;
4413 }
4414 }
4415 /**
4416 * @private
4417 * @param {?} name
4418 * @return {?}
4419 */
4420 _getTrigger(name) {
4421 /** @type {?} */
4422 const trigger = this._triggers[name];
4423 if (!trigger) {
4424 throw new Error(`The provided animation trigger "${name}" has not been registered!`);
4425 }
4426 return trigger;
4427 }
4428 /**
4429 * @param {?} element
4430 * @param {?} triggerName
4431 * @param {?} value
4432 * @param {?=} defaultToFallback
4433 * @return {?}
4434 */
4435 trigger(element, triggerName, value, defaultToFallback = true) {
4436 /** @type {?} */
4437 const trigger = this._getTrigger(triggerName);
4438 /** @type {?} */
4439 const player = new TransitionAnimationPlayer(this.id, triggerName, element);
4440 /** @type {?} */
4441 let triggersWithStates = this._engine.statesByElement.get(element);
4442 if (!triggersWithStates) {
4443 addClass(element, NG_TRIGGER_CLASSNAME);
4444 addClass(element, NG_TRIGGER_CLASSNAME + '-' + triggerName);
4445 this._engine.statesByElement.set(element, triggersWithStates = {});
4446 }
4447 /** @type {?} */
4448 let fromState = triggersWithStates[triggerName];
4449 /** @type {?} */
4450 const toState = new StateValue(value, this.id);
4451 /** @type {?} */
4452 const isObj = value && value.hasOwnProperty('value');
4453 if (!isObj && fromState) {
4454 toState.absorbOptions(fromState.options);
4455 }
4456 triggersWithStates[triggerName] = toState;
4457 if (!fromState) {
4458 fromState = DEFAULT_STATE_VALUE;
4459 }
4460 /** @type {?} */
4461 const isRemoval = toState.value === VOID_VALUE;
4462 // normally this isn't reached by here, however, if an object expression
4463 // is passed in then it may be a new object each time. Comparing the value
4464 // is important since that will stay the same despite there being a new object.
4465 // The removal arc here is special cased because the same element is triggered
4466 // twice in the event that it contains animations on the outer/inner portions
4467 // of the host container
4468 if (!isRemoval && fromState.value === toState.value) {
4469 // this means that despite the value not changing, some inner params
4470 // have changed which means that the animation final styles need to be applied
4471 if (!objEquals(fromState.params, toState.params)) {
4472 /** @type {?} */
4473 const errors = [];
4474 /** @type {?} */
4475 const fromStyles = trigger.matchStyles(fromState.value, fromState.params, errors);
4476 /** @type {?} */
4477 const toStyles = trigger.matchStyles(toState.value, toState.params, errors);
4478 if (errors.length) {
4479 this._engine.reportError(errors);
4480 }
4481 else {
4482 this._engine.afterFlush((/**
4483 * @return {?}
4484 */
4485 () => {
4486 eraseStyles(element, fromStyles);
4487 setStyles(element, toStyles);
4488 }));
4489 }
4490 }
4491 return;
4492 }
4493 /** @type {?} */
4494 const playersOnElement = getOrSetAsInMap(this._engine.playersByElement, element, []);
4495 playersOnElement.forEach((/**
4496 * @param {?} player
4497 * @return {?}
4498 */
4499 player => {
4500 // only remove the player if it is queued on the EXACT same trigger/namespace
4501 // we only also deal with queued players here because if the animation has
4502 // started then we want to keep the player alive until the flush happens
4503 // (which is where the previousPlayers are passed into the new palyer)
4504 if (player.namespaceId == this.id && player.triggerName == triggerName && player.queued) {
4505 player.destroy();
4506 }
4507 }));
4508 /** @type {?} */
4509 let transition = trigger.matchTransition(fromState.value, toState.value, element, toState.params);
4510 /** @type {?} */
4511 let isFallbackTransition = false;
4512 if (!transition) {
4513 if (!defaultToFallback)
4514 return;
4515 transition = trigger.fallbackTransition;
4516 isFallbackTransition = true;
4517 }
4518 this._engine.totalQueuedPlayers++;
4519 this._queue.push({ element, triggerName, transition, fromState, toState, player, isFallbackTransition });
4520 if (!isFallbackTransition) {
4521 addClass(element, QUEUED_CLASSNAME);
4522 player.onStart((/**
4523 * @return {?}
4524 */
4525 () => { removeClass(element, QUEUED_CLASSNAME); }));
4526 }
4527 player.onDone((/**
4528 * @return {?}
4529 */
4530 () => {
4531 /** @type {?} */
4532 let index = this.players.indexOf(player);
4533 if (index >= 0) {
4534 this.players.splice(index, 1);
4535 }
4536 /** @type {?} */
4537 const players = this._engine.playersByElement.get(element);
4538 if (players) {
4539 /** @type {?} */
4540 let index = players.indexOf(player);
4541 if (index >= 0) {
4542 players.splice(index, 1);
4543 }
4544 }
4545 }));
4546 this.players.push(player);
4547 playersOnElement.push(player);
4548 return player;
4549 }
4550 /**
4551 * @param {?} name
4552 * @return {?}
4553 */
4554 deregister(name) {
4555 delete this._triggers[name];
4556 this._engine.statesByElement.forEach((/**
4557 * @param {?} stateMap
4558 * @param {?} element
4559 * @return {?}
4560 */
4561 (stateMap, element) => { delete stateMap[name]; }));
4562 this._elementListeners.forEach((/**
4563 * @param {?} listeners
4564 * @param {?} element
4565 * @return {?}
4566 */
4567 (listeners, element) => {
4568 this._elementListeners.set(element, listeners.filter((/**
4569 * @param {?} entry
4570 * @return {?}
4571 */
4572 entry => { return entry.name != name; })));
4573 }));
4574 }
4575 /**
4576 * @param {?} element
4577 * @return {?}
4578 */
4579 clearElementCache(element) {
4580 this._engine.statesByElement.delete(element);
4581 this._elementListeners.delete(element);
4582 /** @type {?} */
4583 const elementPlayers = this._engine.playersByElement.get(element);
4584 if (elementPlayers) {
4585 elementPlayers.forEach((/**
4586 * @param {?} player
4587 * @return {?}
4588 */
4589 player => player.destroy()));
4590 this._engine.playersByElement.delete(element);
4591 }
4592 }
4593 /**
4594 * @private
4595 * @param {?} rootElement
4596 * @param {?} context
4597 * @return {?}
4598 */
4599 _signalRemovalForInnerTriggers(rootElement, context) {
4600 /** @type {?} */
4601 const elements = this._engine.driver.query(rootElement, NG_TRIGGER_SELECTOR, true);
4602 // emulate a leave animation for all inner nodes within this node.
4603 // If there are no animations found for any of the nodes then clear the cache
4604 // for the element.
4605 elements.forEach((/**
4606 * @param {?} elm
4607 * @return {?}
4608 */
4609 elm => {
4610 // this means that an inner remove() operation has already kicked off
4611 // the animation on this element...
4612 if (elm[REMOVAL_FLAG])
4613 return;
4614 /** @type {?} */
4615 const namespaces = this._engine.fetchNamespacesByElement(elm);
4616 if (namespaces.size) {
4617 namespaces.forEach((/**
4618 * @param {?} ns
4619 * @return {?}
4620 */
4621 ns => ns.triggerLeaveAnimation(elm, context, false, true)));
4622 }
4623 else {
4624 this.clearElementCache(elm);
4625 }
4626 }));
4627 // If the child elements were removed along with the parent, their animations might not
4628 // have completed. Clear all the elements from the cache so we don't end up with a memory leak.
4629 this._engine.afterFlushAnimationsDone((/**
4630 * @return {?}
4631 */
4632 () => elements.forEach((/**
4633 * @param {?} elm
4634 * @return {?}
4635 */
4636 elm => this.clearElementCache(elm)))));
4637 }
4638 /**
4639 * @param {?} element
4640 * @param {?} context
4641 * @param {?=} destroyAfterComplete
4642 * @param {?=} defaultToFallback
4643 * @return {?}
4644 */
4645 triggerLeaveAnimation(element, context, destroyAfterComplete, defaultToFallback) {
4646 /** @type {?} */
4647 const triggerStates = this._engine.statesByElement.get(element);
4648 if (triggerStates) {
4649 /** @type {?} */
4650 const players = [];
4651 Object.keys(triggerStates).forEach((/**
4652 * @param {?} triggerName
4653 * @return {?}
4654 */
4655 triggerName => {
4656 // this check is here in the event that an element is removed
4657 // twice (both on the host level and the component level)
4658 if (this._triggers[triggerName]) {
4659 /** @type {?} */
4660 const player = this.trigger(element, triggerName, VOID_VALUE, defaultToFallback);
4661 if (player) {
4662 players.push(player);
4663 }
4664 }
4665 }));
4666 if (players.length) {
4667 this._engine.markElementAsRemoved(this.id, element, true, context);
4668 if (destroyAfterComplete) {
4669 optimizeGroupPlayer(players).onDone((/**
4670 * @return {?}
4671 */
4672 () => this._engine.processLeaveNode(element)));
4673 }
4674 return true;
4675 }
4676 }
4677 return false;
4678 }
4679 /**
4680 * @param {?} element
4681 * @return {?}
4682 */
4683 prepareLeaveAnimationListeners(element) {
4684 /** @type {?} */
4685 const listeners = this._elementListeners.get(element);
4686 if (listeners) {
4687 /** @type {?} */
4688 const visitedTriggers = new Set();
4689 listeners.forEach((/**
4690 * @param {?} listener
4691 * @return {?}
4692 */
4693 listener => {
4694 /** @type {?} */
4695 const triggerName = listener.name;
4696 if (visitedTriggers.has(triggerName))
4697 return;
4698 visitedTriggers.add(triggerName);
4699 /** @type {?} */
4700 const trigger = this._triggers[triggerName];
4701 /** @type {?} */
4702 const transition = trigger.fallbackTransition;
4703 /** @type {?} */
4704 const elementStates = (/** @type {?} */ (this._engine.statesByElement.get(element)));
4705 /** @type {?} */
4706 const fromState = elementStates[triggerName] || DEFAULT_STATE_VALUE;
4707 /** @type {?} */
4708 const toState = new StateValue(VOID_VALUE);
4709 /** @type {?} */
4710 const player = new TransitionAnimationPlayer(this.id, triggerName, element);
4711 this._engine.totalQueuedPlayers++;
4712 this._queue.push({
4713 element,
4714 triggerName,
4715 transition,
4716 fromState,
4717 toState,
4718 player,
4719 isFallbackTransition: true
4720 });
4721 }));
4722 }
4723 }
4724 /**
4725 * @param {?} element
4726 * @param {?} context
4727 * @return {?}
4728 */
4729 removeNode(element, context) {
4730 /** @type {?} */
4731 const engine = this._engine;
4732 if (element.childElementCount) {
4733 this._signalRemovalForInnerTriggers(element, context);
4734 }
4735 // this means that a * => VOID animation was detected and kicked off
4736 if (this.triggerLeaveAnimation(element, context, true))
4737 return;
4738 // find the player that is animating and make sure that the
4739 // removal is delayed until that player has completed
4740 /** @type {?} */
4741 let containsPotentialParentTransition = false;
4742 if (engine.totalAnimations) {
4743 /** @type {?} */
4744 const currentPlayers = engine.players.length ? engine.playersByQueriedElement.get(element) : [];
4745 // when this `if statement` does not continue forward it means that
4746 // a previous animation query has selected the current element and
4747 // is animating it. In this situation want to continue forwards and
4748 // allow the element to be queued up for animation later.
4749 if (currentPlayers && currentPlayers.length) {
4750 containsPotentialParentTransition = true;
4751 }
4752 else {
4753 /** @type {?} */
4754 let parent = element;
4755 while (parent = parent.parentNode) {
4756 /** @type {?} */
4757 const triggers = engine.statesByElement.get(parent);
4758 if (triggers) {
4759 containsPotentialParentTransition = true;
4760 break;
4761 }
4762 }
4763 }
4764 }
4765 // at this stage we know that the element will either get removed
4766 // during flush or will be picked up by a parent query. Either way
4767 // we need to fire the listeners for this element when it DOES get
4768 // removed (once the query parent animation is done or after flush)
4769 this.prepareLeaveAnimationListeners(element);
4770 // whether or not a parent has an animation we need to delay the deferral of the leave
4771 // operation until we have more information (which we do after flush() has been called)
4772 if (containsPotentialParentTransition) {
4773 engine.markElementAsRemoved(this.id, element, false, context);
4774 }
4775 else {
4776 /** @type {?} */
4777 const removalFlag = element[REMOVAL_FLAG];
4778 if (!removalFlag || removalFlag === NULL_REMOVAL_STATE) {
4779 // we do this after the flush has occurred such
4780 // that the callbacks can be fired
4781 engine.afterFlush((/**
4782 * @return {?}
4783 */
4784 () => this.clearElementCache(element)));
4785 engine.destroyInnerAnimations(element);
4786 engine._onRemovalComplete(element, context);
4787 }
4788 }
4789 }
4790 /**
4791 * @param {?} element
4792 * @param {?} parent
4793 * @return {?}
4794 */
4795 insertNode(element, parent) { addClass(element, this._hostClassName); }
4796 /**
4797 * @param {?} microtaskId
4798 * @return {?}
4799 */
4800 drainQueuedTransitions(microtaskId) {
4801 /** @type {?} */
4802 const instructions = [];
4803 this._queue.forEach((/**
4804 * @param {?} entry
4805 * @return {?}
4806 */
4807 entry => {
4808 /** @type {?} */
4809 const player = entry.player;
4810 if (player.destroyed)
4811 return;
4812 /** @type {?} */
4813 const element = entry.element;
4814 /** @type {?} */
4815 const listeners = this._elementListeners.get(element);
4816 if (listeners) {
4817 listeners.forEach((/**
4818 * @param {?} listener
4819 * @return {?}
4820 */
4821 (listener) => {
4822 if (listener.name == entry.triggerName) {
4823 /** @type {?} */
4824 const baseEvent = makeAnimationEvent(element, entry.triggerName, entry.fromState.value, entry.toState.value);
4825 ((/** @type {?} */ (baseEvent)))['_data'] = microtaskId;
4826 listenOnPlayer(entry.player, listener.phase, baseEvent, listener.callback);
4827 }
4828 }));
4829 }
4830 if (player.markedForDestroy) {
4831 this._engine.afterFlush((/**
4832 * @return {?}
4833 */
4834 () => {
4835 // now we can destroy the element properly since the event listeners have
4836 // been bound to the player
4837 player.destroy();
4838 }));
4839 }
4840 else {
4841 instructions.push(entry);
4842 }
4843 }));
4844 this._queue = [];
4845 return instructions.sort((/**
4846 * @param {?} a
4847 * @param {?} b
4848 * @return {?}
4849 */
4850 (a, b) => {
4851 // if depCount == 0 them move to front
4852 // otherwise if a contains b then move back
4853 /** @type {?} */
4854 const d0 = a.transition.ast.depCount;
4855 /** @type {?} */
4856 const d1 = b.transition.ast.depCount;
4857 if (d0 == 0 || d1 == 0) {
4858 return d0 - d1;
4859 }
4860 return this._engine.driver.containsElement(a.element, b.element) ? 1 : -1;
4861 }));
4862 }
4863 /**
4864 * @param {?} context
4865 * @return {?}
4866 */
4867 destroy(context) {
4868 this.players.forEach((/**
4869 * @param {?} p
4870 * @return {?}
4871 */
4872 p => p.destroy()));
4873 this._signalRemovalForInnerTriggers(this.hostElement, context);
4874 }
4875 /**
4876 * @param {?} element
4877 * @return {?}
4878 */
4879 elementContainsData(element) {
4880 /** @type {?} */
4881 let containsData = false;
4882 if (this._elementListeners.has(element))
4883 containsData = true;
4884 containsData =
4885 (this._queue.find((/**
4886 * @param {?} entry
4887 * @return {?}
4888 */
4889 entry => entry.element === element)) ? true : false) || containsData;
4890 return containsData;
4891 }
4892}
4893if (false) {
4894 /** @type {?} */
4895 AnimationTransitionNamespace.prototype.players;
4896 /**
4897 * @type {?}
4898 * @private
4899 */
4900 AnimationTransitionNamespace.prototype._triggers;
4901 /**
4902 * @type {?}
4903 * @private
4904 */
4905 AnimationTransitionNamespace.prototype._queue;
4906 /**
4907 * @type {?}
4908 * @private
4909 */
4910 AnimationTransitionNamespace.prototype._elementListeners;
4911 /**
4912 * @type {?}
4913 * @private
4914 */
4915 AnimationTransitionNamespace.prototype._hostClassName;
4916 /** @type {?} */
4917 AnimationTransitionNamespace.prototype.id;
4918 /** @type {?} */
4919 AnimationTransitionNamespace.prototype.hostElement;
4920 /**
4921 * @type {?}
4922 * @private
4923 */
4924 AnimationTransitionNamespace.prototype._engine;
4925}
4926/**
4927 * @record
4928 */
4929function QueuedTransition() { }
4930if (false) {
4931 /** @type {?} */
4932 QueuedTransition.prototype.element;
4933 /** @type {?} */
4934 QueuedTransition.prototype.instruction;
4935 /** @type {?} */
4936 QueuedTransition.prototype.player;
4937}
4938class TransitionAnimationEngine {
4939 /**
4940 * @param {?} bodyNode
4941 * @param {?} driver
4942 * @param {?} _normalizer
4943 */
4944 constructor(bodyNode, driver, _normalizer) {
4945 this.bodyNode = bodyNode;
4946 this.driver = driver;
4947 this._normalizer = _normalizer;
4948 this.players = [];
4949 this.newHostElements = new Map();
4950 this.playersByElement = new Map();
4951 this.playersByQueriedElement = new Map();
4952 this.statesByElement = new Map();
4953 this.disabledNodes = new Set();
4954 this.totalAnimations = 0;
4955 this.totalQueuedPlayers = 0;
4956 this._namespaceLookup = {};
4957 this._namespaceList = [];
4958 this._flushFns = [];
4959 this._whenQuietFns = [];
4960 this.namespacesByHostElement = new Map();
4961 this.collectedEnterElements = [];
4962 this.collectedLeaveElements = [];
4963 // this method is designed to be overridden by the code that uses this engine
4964 this.onRemovalComplete = (/**
4965 * @param {?} element
4966 * @param {?} context
4967 * @return {?}
4968 */
4969 (element, context) => { });
4970 }
4971 /**
4972 * \@internal
4973 * @param {?} element
4974 * @param {?} context
4975 * @return {?}
4976 */
4977 _onRemovalComplete(element, context) { this.onRemovalComplete(element, context); }
4978 /**
4979 * @return {?}
4980 */
4981 get queuedPlayers() {
4982 /** @type {?} */
4983 const players = [];
4984 this._namespaceList.forEach((/**
4985 * @param {?} ns
4986 * @return {?}
4987 */
4988 ns => {
4989 ns.players.forEach((/**
4990 * @param {?} player
4991 * @return {?}
4992 */
4993 player => {
4994 if (player.queued) {
4995 players.push(player);
4996 }
4997 }));
4998 }));
4999 return players;
5000 }
5001 /**
5002 * @param {?} namespaceId
5003 * @param {?} hostElement
5004 * @return {?}
5005 */
5006 createNamespace(namespaceId, hostElement) {
5007 /** @type {?} */
5008 const ns = new AnimationTransitionNamespace(namespaceId, hostElement, this);
5009 if (hostElement.parentNode) {
5010 this._balanceNamespaceList(ns, hostElement);
5011 }
5012 else {
5013 // defer this later until flush during when the host element has
5014 // been inserted so that we know exactly where to place it in
5015 // the namespace list
5016 this.newHostElements.set(hostElement, ns);
5017 // given that this host element is apart of the animation code, it
5018 // may or may not be inserted by a parent node that is an of an
5019 // animation renderer type. If this happens then we can still have
5020 // access to this item when we query for :enter nodes. If the parent
5021 // is a renderer then the set data-structure will normalize the entry
5022 this.collectEnterElement(hostElement);
5023 }
5024 return this._namespaceLookup[namespaceId] = ns;
5025 }
5026 /**
5027 * @private
5028 * @param {?} ns
5029 * @param {?} hostElement
5030 * @return {?}
5031 */
5032 _balanceNamespaceList(ns, hostElement) {
5033 /** @type {?} */
5034 const limit = this._namespaceList.length - 1;
5035 if (limit >= 0) {
5036 /** @type {?} */
5037 let found = false;
5038 for (let i = limit; i >= 0; i--) {
5039 /** @type {?} */
5040 const nextNamespace = this._namespaceList[i];
5041 if (this.driver.containsElement(nextNamespace.hostElement, hostElement)) {
5042 this._namespaceList.splice(i + 1, 0, ns);
5043 found = true;
5044 break;
5045 }
5046 }
5047 if (!found) {
5048 this._namespaceList.splice(0, 0, ns);
5049 }
5050 }
5051 else {
5052 this._namespaceList.push(ns);
5053 }
5054 this.namespacesByHostElement.set(hostElement, ns);
5055 return ns;
5056 }
5057 /**
5058 * @param {?} namespaceId
5059 * @param {?} hostElement
5060 * @return {?}
5061 */
5062 register(namespaceId, hostElement) {
5063 /** @type {?} */
5064 let ns = this._namespaceLookup[namespaceId];
5065 if (!ns) {
5066 ns = this.createNamespace(namespaceId, hostElement);
5067 }
5068 return ns;
5069 }
5070 /**
5071 * @param {?} namespaceId
5072 * @param {?} name
5073 * @param {?} trigger
5074 * @return {?}
5075 */
5076 registerTrigger(namespaceId, name, trigger) {
5077 /** @type {?} */
5078 let ns = this._namespaceLookup[namespaceId];
5079 if (ns && ns.register(name, trigger)) {
5080 this.totalAnimations++;
5081 }
5082 }
5083 /**
5084 * @param {?} namespaceId
5085 * @param {?} context
5086 * @return {?}
5087 */
5088 destroy(namespaceId, context) {
5089 if (!namespaceId)
5090 return;
5091 /** @type {?} */
5092 const ns = this._fetchNamespace(namespaceId);
5093 this.afterFlush((/**
5094 * @return {?}
5095 */
5096 () => {
5097 this.namespacesByHostElement.delete(ns.hostElement);
5098 delete this._namespaceLookup[namespaceId];
5099 /** @type {?} */
5100 const index = this._namespaceList.indexOf(ns);
5101 if (index >= 0) {
5102 this._namespaceList.splice(index, 1);
5103 }
5104 }));
5105 this.afterFlushAnimationsDone((/**
5106 * @return {?}
5107 */
5108 () => ns.destroy(context)));
5109 }
5110 /**
5111 * @private
5112 * @param {?} id
5113 * @return {?}
5114 */
5115 _fetchNamespace(id) { return this._namespaceLookup[id]; }
5116 /**
5117 * @param {?} element
5118 * @return {?}
5119 */
5120 fetchNamespacesByElement(element) {
5121 // normally there should only be one namespace per element, however
5122 // if @triggers are placed on both the component element and then
5123 // its host element (within the component code) then there will be
5124 // two namespaces returned. We use a set here to simply the dedupe
5125 // of namespaces incase there are multiple triggers both the elm and host
5126 /** @type {?} */
5127 const namespaces = new Set();
5128 /** @type {?} */
5129 const elementStates = this.statesByElement.get(element);
5130 if (elementStates) {
5131 /** @type {?} */
5132 const keys = Object.keys(elementStates);
5133 for (let i = 0; i < keys.length; i++) {
5134 /** @type {?} */
5135 const nsId = elementStates[keys[i]].namespaceId;
5136 if (nsId) {
5137 /** @type {?} */
5138 const ns = this._fetchNamespace(nsId);
5139 if (ns) {
5140 namespaces.add(ns);
5141 }
5142 }
5143 }
5144 }
5145 return namespaces;
5146 }
5147 /**
5148 * @param {?} namespaceId
5149 * @param {?} element
5150 * @param {?} name
5151 * @param {?} value
5152 * @return {?}
5153 */
5154 trigger(namespaceId, element, name, value) {
5155 if (isElementNode(element)) {
5156 /** @type {?} */
5157 const ns = this._fetchNamespace(namespaceId);
5158 if (ns) {
5159 ns.trigger(element, name, value);
5160 return true;
5161 }
5162 }
5163 return false;
5164 }
5165 /**
5166 * @param {?} namespaceId
5167 * @param {?} element
5168 * @param {?} parent
5169 * @param {?} insertBefore
5170 * @return {?}
5171 */
5172 insertNode(namespaceId, element, parent, insertBefore) {
5173 if (!isElementNode(element))
5174 return;
5175 // special case for when an element is removed and reinserted (move operation)
5176 // when this occurs we do not want to use the element for deletion later
5177 /** @type {?} */
5178 const details = (/** @type {?} */ (element[REMOVAL_FLAG]));
5179 if (details && details.setForRemoval) {
5180 details.setForRemoval = false;
5181 details.setForMove = true;
5182 /** @type {?} */
5183 const index = this.collectedLeaveElements.indexOf(element);
5184 if (index >= 0) {
5185 this.collectedLeaveElements.splice(index, 1);
5186 }
5187 }
5188 // in the event that the namespaceId is blank then the caller
5189 // code does not contain any animation code in it, but it is
5190 // just being called so that the node is marked as being inserted
5191 if (namespaceId) {
5192 /** @type {?} */
5193 const ns = this._fetchNamespace(namespaceId);
5194 // This if-statement is a workaround for router issue #21947.
5195 // The router sometimes hits a race condition where while a route
5196 // is being instantiated a new navigation arrives, triggering leave
5197 // animation of DOM that has not been fully initialized, until this
5198 // is resolved, we need to handle the scenario when DOM is not in a
5199 // consistent state during the animation.
5200 if (ns) {
5201 ns.insertNode(element, parent);
5202 }
5203 }
5204 // only *directives and host elements are inserted before
5205 if (insertBefore) {
5206 this.collectEnterElement(element);
5207 }
5208 }
5209 /**
5210 * @param {?} element
5211 * @return {?}
5212 */
5213 collectEnterElement(element) { this.collectedEnterElements.push(element); }
5214 /**
5215 * @param {?} element
5216 * @param {?} value
5217 * @return {?}
5218 */
5219 markElementAsDisabled(element, value) {
5220 if (value) {
5221 if (!this.disabledNodes.has(element)) {
5222 this.disabledNodes.add(element);
5223 addClass(element, DISABLED_CLASSNAME);
5224 }
5225 }
5226 else if (this.disabledNodes.has(element)) {
5227 this.disabledNodes.delete(element);
5228 removeClass(element, DISABLED_CLASSNAME);
5229 }
5230 }
5231 /**
5232 * @param {?} namespaceId
5233 * @param {?} element
5234 * @param {?} isHostElement
5235 * @param {?} context
5236 * @return {?}
5237 */
5238 removeNode(namespaceId, element, isHostElement, context) {
5239 if (isElementNode(element)) {
5240 /** @type {?} */
5241 const ns = namespaceId ? this._fetchNamespace(namespaceId) : null;
5242 if (ns) {
5243 ns.removeNode(element, context);
5244 }
5245 else {
5246 this.markElementAsRemoved(namespaceId, element, false, context);
5247 }
5248 if (isHostElement) {
5249 /** @type {?} */
5250 const hostNS = this.namespacesByHostElement.get(element);
5251 if (hostNS && hostNS.id !== namespaceId) {
5252 hostNS.removeNode(element, context);
5253 }
5254 }
5255 }
5256 else {
5257 this._onRemovalComplete(element, context);
5258 }
5259 }
5260 /**
5261 * @param {?} namespaceId
5262 * @param {?} element
5263 * @param {?=} hasAnimation
5264 * @param {?=} context
5265 * @return {?}
5266 */
5267 markElementAsRemoved(namespaceId, element, hasAnimation, context) {
5268 this.collectedLeaveElements.push(element);
5269 element[REMOVAL_FLAG] = {
5270 namespaceId,
5271 setForRemoval: context, hasAnimation,
5272 removedBeforeQueried: false
5273 };
5274 }
5275 /**
5276 * @param {?} namespaceId
5277 * @param {?} element
5278 * @param {?} name
5279 * @param {?} phase
5280 * @param {?} callback
5281 * @return {?}
5282 */
5283 listen(namespaceId, element, name, phase, callback) {
5284 if (isElementNode(element)) {
5285 return this._fetchNamespace(namespaceId).listen(element, name, phase, callback);
5286 }
5287 return (/**
5288 * @return {?}
5289 */
5290 () => { });
5291 }
5292 /**
5293 * @private
5294 * @param {?} entry
5295 * @param {?} subTimelines
5296 * @param {?} enterClassName
5297 * @param {?} leaveClassName
5298 * @param {?=} skipBuildAst
5299 * @return {?}
5300 */
5301 _buildInstruction(entry, subTimelines, enterClassName, leaveClassName, skipBuildAst) {
5302 return entry.transition.build(this.driver, entry.element, entry.fromState.value, entry.toState.value, enterClassName, leaveClassName, entry.fromState.options, entry.toState.options, subTimelines, skipBuildAst);
5303 }
5304 /**
5305 * @param {?} containerElement
5306 * @return {?}
5307 */
5308 destroyInnerAnimations(containerElement) {
5309 /** @type {?} */
5310 let elements = this.driver.query(containerElement, NG_TRIGGER_SELECTOR, true);
5311 elements.forEach((/**
5312 * @param {?} element
5313 * @return {?}
5314 */
5315 element => this.destroyActiveAnimationsForElement(element)));
5316 if (this.playersByQueriedElement.size == 0)
5317 return;
5318 elements = this.driver.query(containerElement, NG_ANIMATING_SELECTOR, true);
5319 elements.forEach((/**
5320 * @param {?} element
5321 * @return {?}
5322 */
5323 element => this.finishActiveQueriedAnimationOnElement(element)));
5324 }
5325 /**
5326 * @param {?} element
5327 * @return {?}
5328 */
5329 destroyActiveAnimationsForElement(element) {
5330 /** @type {?} */
5331 const players = this.playersByElement.get(element);
5332 if (players) {
5333 players.forEach((/**
5334 * @param {?} player
5335 * @return {?}
5336 */
5337 player => {
5338 // special case for when an element is set for destruction, but hasn't started.
5339 // in this situation we want to delay the destruction until the flush occurs
5340 // so that any event listeners attached to the player are triggered.
5341 if (player.queued) {
5342 player.markedForDestroy = true;
5343 }
5344 else {
5345 player.destroy();
5346 }
5347 }));
5348 }
5349 }
5350 /**
5351 * @param {?} element
5352 * @return {?}
5353 */
5354 finishActiveQueriedAnimationOnElement(element) {
5355 /** @type {?} */
5356 const players = this.playersByQueriedElement.get(element);
5357 if (players) {
5358 players.forEach((/**
5359 * @param {?} player
5360 * @return {?}
5361 */
5362 player => player.finish()));
5363 }
5364 }
5365 /**
5366 * @return {?}
5367 */
5368 whenRenderingDone() {
5369 return new Promise((/**
5370 * @param {?} resolve
5371 * @return {?}
5372 */
5373 resolve => {
5374 if (this.players.length) {
5375 return optimizeGroupPlayer(this.players).onDone((/**
5376 * @return {?}
5377 */
5378 () => resolve()));
5379 }
5380 else {
5381 resolve();
5382 }
5383 }));
5384 }
5385 /**
5386 * @param {?} element
5387 * @return {?}
5388 */
5389 processLeaveNode(element) {
5390 /** @type {?} */
5391 const details = (/** @type {?} */ (element[REMOVAL_FLAG]));
5392 if (details && details.setForRemoval) {
5393 // this will prevent it from removing it twice
5394 element[REMOVAL_FLAG] = NULL_REMOVAL_STATE;
5395 if (details.namespaceId) {
5396 this.destroyInnerAnimations(element);
5397 /** @type {?} */
5398 const ns = this._fetchNamespace(details.namespaceId);
5399 if (ns) {
5400 ns.clearElementCache(element);
5401 }
5402 }
5403 this._onRemovalComplete(element, details.setForRemoval);
5404 }
5405 if (this.driver.matchesElement(element, DISABLED_SELECTOR)) {
5406 this.markElementAsDisabled(element, false);
5407 }
5408 this.driver.query(element, DISABLED_SELECTOR, true).forEach((/**
5409 * @param {?} node
5410 * @return {?}
5411 */
5412 node => {
5413 this.markElementAsDisabled(node, false);
5414 }));
5415 }
5416 /**
5417 * @param {?=} microtaskId
5418 * @return {?}
5419 */
5420 flush(microtaskId = -1) {
5421 /** @type {?} */
5422 let players = [];
5423 if (this.newHostElements.size) {
5424 this.newHostElements.forEach((/**
5425 * @param {?} ns
5426 * @param {?} element
5427 * @return {?}
5428 */
5429 (ns, element) => this._balanceNamespaceList(ns, element)));
5430 this.newHostElements.clear();
5431 }
5432 if (this.totalAnimations && this.collectedEnterElements.length) {
5433 for (let i = 0; i < this.collectedEnterElements.length; i++) {
5434 /** @type {?} */
5435 const elm = this.collectedEnterElements[i];
5436 addClass(elm, STAR_CLASSNAME);
5437 }
5438 }
5439 if (this._namespaceList.length &&
5440 (this.totalQueuedPlayers || this.collectedLeaveElements.length)) {
5441 /** @type {?} */
5442 const cleanupFns = [];
5443 try {
5444 players = this._flushAnimations(cleanupFns, microtaskId);
5445 }
5446 finally {
5447 for (let i = 0; i < cleanupFns.length; i++) {
5448 cleanupFns[i]();
5449 }
5450 }
5451 }
5452 else {
5453 for (let i = 0; i < this.collectedLeaveElements.length; i++) {
5454 /** @type {?} */
5455 const element = this.collectedLeaveElements[i];
5456 this.processLeaveNode(element);
5457 }
5458 }
5459 this.totalQueuedPlayers = 0;
5460 this.collectedEnterElements.length = 0;
5461 this.collectedLeaveElements.length = 0;
5462 this._flushFns.forEach((/**
5463 * @param {?} fn
5464 * @return {?}
5465 */
5466 fn => fn()));
5467 this._flushFns = [];
5468 if (this._whenQuietFns.length) {
5469 // we move these over to a variable so that
5470 // if any new callbacks are registered in another
5471 // flush they do not populate the existing set
5472 /** @type {?} */
5473 const quietFns = this._whenQuietFns;
5474 this._whenQuietFns = [];
5475 if (players.length) {
5476 optimizeGroupPlayer(players).onDone((/**
5477 * @return {?}
5478 */
5479 () => { quietFns.forEach((/**
5480 * @param {?} fn
5481 * @return {?}
5482 */
5483 fn => fn())); }));
5484 }
5485 else {
5486 quietFns.forEach((/**
5487 * @param {?} fn
5488 * @return {?}
5489 */
5490 fn => fn()));
5491 }
5492 }
5493 }
5494 /**
5495 * @param {?} errors
5496 * @return {?}
5497 */
5498 reportError(errors) {
5499 throw new Error(`Unable to process animations due to the following failed trigger transitions\n ${errors.join('\n')}`);
5500 }
5501 /**
5502 * @private
5503 * @param {?} cleanupFns
5504 * @param {?} microtaskId
5505 * @return {?}
5506 */
5507 _flushAnimations(cleanupFns, microtaskId) {
5508 /** @type {?} */
5509 const subTimelines = new ElementInstructionMap();
5510 /** @type {?} */
5511 const skippedPlayers = [];
5512 /** @type {?} */
5513 const skippedPlayersMap = new Map();
5514 /** @type {?} */
5515 const queuedInstructions = [];
5516 /** @type {?} */
5517 const queriedElements = new Map();
5518 /** @type {?} */
5519 const allPreStyleElements = new Map();
5520 /** @type {?} */
5521 const allPostStyleElements = new Map();
5522 /** @type {?} */
5523 const disabledElementsSet = new Set();
5524 this.disabledNodes.forEach((/**
5525 * @param {?} node
5526 * @return {?}
5527 */
5528 node => {
5529 disabledElementsSet.add(node);
5530 /** @type {?} */
5531 const nodesThatAreDisabled = this.driver.query(node, QUEUED_SELECTOR, true);
5532 for (let i = 0; i < nodesThatAreDisabled.length; i++) {
5533 disabledElementsSet.add(nodesThatAreDisabled[i]);
5534 }
5535 }));
5536 /** @type {?} */
5537 const bodyNode = this.bodyNode;
5538 /** @type {?} */
5539 const allTriggerElements = Array.from(this.statesByElement.keys());
5540 /** @type {?} */
5541 const enterNodeMap = buildRootMap(allTriggerElements, this.collectedEnterElements);
5542 // this must occur before the instructions are built below such that
5543 // the :enter queries match the elements (since the timeline queries
5544 // are fired during instruction building).
5545 /** @type {?} */
5546 const enterNodeMapIds = new Map();
5547 /** @type {?} */
5548 let i = 0;
5549 enterNodeMap.forEach((/**
5550 * @param {?} nodes
5551 * @param {?} root
5552 * @return {?}
5553 */
5554 (nodes, root) => {
5555 /** @type {?} */
5556 const className = ENTER_CLASSNAME + i++;
5557 enterNodeMapIds.set(root, className);
5558 nodes.forEach((/**
5559 * @param {?} node
5560 * @return {?}
5561 */
5562 node => addClass(node, className)));
5563 }));
5564 /** @type {?} */
5565 const allLeaveNodes = [];
5566 /** @type {?} */
5567 const mergedLeaveNodes = new Set();
5568 /** @type {?} */
5569 const leaveNodesWithoutAnimations = new Set();
5570 for (let i = 0; i < this.collectedLeaveElements.length; i++) {
5571 /** @type {?} */
5572 const element = this.collectedLeaveElements[i];
5573 /** @type {?} */
5574 const details = (/** @type {?} */ (element[REMOVAL_FLAG]));
5575 if (details && details.setForRemoval) {
5576 allLeaveNodes.push(element);
5577 mergedLeaveNodes.add(element);
5578 if (details.hasAnimation) {
5579 this.driver.query(element, STAR_SELECTOR, true).forEach((/**
5580 * @param {?} elm
5581 * @return {?}
5582 */
5583 elm => mergedLeaveNodes.add(elm)));
5584 }
5585 else {
5586 leaveNodesWithoutAnimations.add(element);
5587 }
5588 }
5589 }
5590 /** @type {?} */
5591 const leaveNodeMapIds = new Map();
5592 /** @type {?} */
5593 const leaveNodeMap = buildRootMap(allTriggerElements, Array.from(mergedLeaveNodes));
5594 leaveNodeMap.forEach((/**
5595 * @param {?} nodes
5596 * @param {?} root
5597 * @return {?}
5598 */
5599 (nodes, root) => {
5600 /** @type {?} */
5601 const className = LEAVE_CLASSNAME + i++;
5602 leaveNodeMapIds.set(root, className);
5603 nodes.forEach((/**
5604 * @param {?} node
5605 * @return {?}
5606 */
5607 node => addClass(node, className)));
5608 }));
5609 cleanupFns.push((/**
5610 * @return {?}
5611 */
5612 () => {
5613 enterNodeMap.forEach((/**
5614 * @param {?} nodes
5615 * @param {?} root
5616 * @return {?}
5617 */
5618 (nodes, root) => {
5619 /** @type {?} */
5620 const className = (/** @type {?} */ (enterNodeMapIds.get(root)));
5621 nodes.forEach((/**
5622 * @param {?} node
5623 * @return {?}
5624 */
5625 node => removeClass(node, className)));
5626 }));
5627 leaveNodeMap.forEach((/**
5628 * @param {?} nodes
5629 * @param {?} root
5630 * @return {?}
5631 */
5632 (nodes, root) => {
5633 /** @type {?} */
5634 const className = (/** @type {?} */ (leaveNodeMapIds.get(root)));
5635 nodes.forEach((/**
5636 * @param {?} node
5637 * @return {?}
5638 */
5639 node => removeClass(node, className)));
5640 }));
5641 allLeaveNodes.forEach((/**
5642 * @param {?} element
5643 * @return {?}
5644 */
5645 element => { this.processLeaveNode(element); }));
5646 }));
5647 /** @type {?} */
5648 const allPlayers = [];
5649 /** @type {?} */
5650 const erroneousTransitions = [];
5651 for (let i = this._namespaceList.length - 1; i >= 0; i--) {
5652 /** @type {?} */
5653 const ns = this._namespaceList[i];
5654 ns.drainQueuedTransitions(microtaskId).forEach((/**
5655 * @param {?} entry
5656 * @return {?}
5657 */
5658 entry => {
5659 /** @type {?} */
5660 const player = entry.player;
5661 /** @type {?} */
5662 const element = entry.element;
5663 allPlayers.push(player);
5664 if (this.collectedEnterElements.length) {
5665 /** @type {?} */
5666 const details = (/** @type {?} */ (element[REMOVAL_FLAG]));
5667 // move animations are currently not supported...
5668 if (details && details.setForMove) {
5669 player.destroy();
5670 return;
5671 }
5672 }
5673 /** @type {?} */
5674 const nodeIsOrphaned = !bodyNode || !this.driver.containsElement(bodyNode, element);
5675 /** @type {?} */
5676 const leaveClassName = (/** @type {?} */ (leaveNodeMapIds.get(element)));
5677 /** @type {?} */
5678 const enterClassName = (/** @type {?} */ (enterNodeMapIds.get(element)));
5679 /** @type {?} */
5680 const instruction = (/** @type {?} */ (this._buildInstruction(entry, subTimelines, enterClassName, leaveClassName, nodeIsOrphaned)));
5681 if (instruction.errors && instruction.errors.length) {
5682 erroneousTransitions.push(instruction);
5683 return;
5684 }
5685 // even though the element may not be apart of the DOM, it may
5686 // still be added at a later point (due to the mechanics of content
5687 // projection and/or dynamic component insertion) therefore it's
5688 // important we still style the element.
5689 if (nodeIsOrphaned) {
5690 player.onStart((/**
5691 * @return {?}
5692 */
5693 () => eraseStyles(element, instruction.fromStyles)));
5694 player.onDestroy((/**
5695 * @return {?}
5696 */
5697 () => setStyles(element, instruction.toStyles)));
5698 skippedPlayers.push(player);
5699 return;
5700 }
5701 // if a unmatched transition is queued to go then it SHOULD NOT render
5702 // an animation and cancel the previously running animations.
5703 if (entry.isFallbackTransition) {
5704 player.onStart((/**
5705 * @return {?}
5706 */
5707 () => eraseStyles(element, instruction.fromStyles)));
5708 player.onDestroy((/**
5709 * @return {?}
5710 */
5711 () => setStyles(element, instruction.toStyles)));
5712 skippedPlayers.push(player);
5713 return;
5714 }
5715 // this means that if a parent animation uses this animation as a sub trigger
5716 // then it will instruct the timeline builder to not add a player delay, but
5717 // instead stretch the first keyframe gap up until the animation starts. The
5718 // reason this is important is to prevent extra initialization styles from being
5719 // required by the user in the animation.
5720 instruction.timelines.forEach((/**
5721 * @param {?} tl
5722 * @return {?}
5723 */
5724 tl => tl.stretchStartingKeyframe = true));
5725 subTimelines.append(element, instruction.timelines);
5726 /** @type {?} */
5727 const tuple = { instruction, player, element };
5728 queuedInstructions.push(tuple);
5729 instruction.queriedElements.forEach((/**
5730 * @param {?} element
5731 * @return {?}
5732 */
5733 element => getOrSetAsInMap(queriedElements, element, []).push(player)));
5734 instruction.preStyleProps.forEach((/**
5735 * @param {?} stringMap
5736 * @param {?} element
5737 * @return {?}
5738 */
5739 (stringMap, element) => {
5740 /** @type {?} */
5741 const props = Object.keys(stringMap);
5742 if (props.length) {
5743 /** @type {?} */
5744 let setVal = (/** @type {?} */ (allPreStyleElements.get(element)));
5745 if (!setVal) {
5746 allPreStyleElements.set(element, setVal = new Set());
5747 }
5748 props.forEach((/**
5749 * @param {?} prop
5750 * @return {?}
5751 */
5752 prop => setVal.add(prop)));
5753 }
5754 }));
5755 instruction.postStyleProps.forEach((/**
5756 * @param {?} stringMap
5757 * @param {?} element
5758 * @return {?}
5759 */
5760 (stringMap, element) => {
5761 /** @type {?} */
5762 const props = Object.keys(stringMap);
5763 /** @type {?} */
5764 let setVal = (/** @type {?} */ (allPostStyleElements.get(element)));
5765 if (!setVal) {
5766 allPostStyleElements.set(element, setVal = new Set());
5767 }
5768 props.forEach((/**
5769 * @param {?} prop
5770 * @return {?}
5771 */
5772 prop => setVal.add(prop)));
5773 }));
5774 }));
5775 }
5776 if (erroneousTransitions.length) {
5777 /** @type {?} */
5778 const errors = [];
5779 erroneousTransitions.forEach((/**
5780 * @param {?} instruction
5781 * @return {?}
5782 */
5783 instruction => {
5784 errors.push(`@${instruction.triggerName} has failed due to:\n`);
5785 (/** @type {?} */ (instruction.errors)).forEach((/**
5786 * @param {?} error
5787 * @return {?}
5788 */
5789 error => errors.push(`- ${error}\n`)));
5790 }));
5791 allPlayers.forEach((/**
5792 * @param {?} player
5793 * @return {?}
5794 */
5795 player => player.destroy()));
5796 this.reportError(errors);
5797 }
5798 /** @type {?} */
5799 const allPreviousPlayersMap = new Map();
5800 // this map works to tell which element in the DOM tree is contained by
5801 // which animation. Further down below this map will get populated once
5802 // the players are built and in doing so it can efficiently figure out
5803 // if a sub player is skipped due to a parent player having priority.
5804 /** @type {?} */
5805 const animationElementMap = new Map();
5806 queuedInstructions.forEach((/**
5807 * @param {?} entry
5808 * @return {?}
5809 */
5810 entry => {
5811 /** @type {?} */
5812 const element = entry.element;
5813 if (subTimelines.has(element)) {
5814 animationElementMap.set(element, element);
5815 this._beforeAnimationBuild(entry.player.namespaceId, entry.instruction, allPreviousPlayersMap);
5816 }
5817 }));
5818 skippedPlayers.forEach((/**
5819 * @param {?} player
5820 * @return {?}
5821 */
5822 player => {
5823 /** @type {?} */
5824 const element = player.element;
5825 /** @type {?} */
5826 const previousPlayers = this._getPreviousPlayers(element, false, player.namespaceId, player.triggerName, null);
5827 previousPlayers.forEach((/**
5828 * @param {?} prevPlayer
5829 * @return {?}
5830 */
5831 prevPlayer => {
5832 getOrSetAsInMap(allPreviousPlayersMap, element, []).push(prevPlayer);
5833 prevPlayer.destroy();
5834 }));
5835 }));
5836 // this is a special case for nodes that will be removed (either by)
5837 // having their own leave animations or by being queried in a container
5838 // that will be removed once a parent animation is complete. The idea
5839 // here is that * styles must be identical to ! styles because of
5840 // backwards compatibility (* is also filled in by default in many places).
5841 // Otherwise * styles will return an empty value or auto since the element
5842 // that is being getComputedStyle'd will not be visible (since * = destination)
5843 /** @type {?} */
5844 const replaceNodes = allLeaveNodes.filter((/**
5845 * @param {?} node
5846 * @return {?}
5847 */
5848 node => {
5849 return replacePostStylesAsPre(node, allPreStyleElements, allPostStyleElements);
5850 }));
5851 // POST STAGE: fill the * styles
5852 /** @type {?} */
5853 const postStylesMap = new Map();
5854 /** @type {?} */
5855 const allLeaveQueriedNodes = cloakAndComputeStyles(postStylesMap, this.driver, leaveNodesWithoutAnimations, allPostStyleElements, AUTO_STYLE);
5856 allLeaveQueriedNodes.forEach((/**
5857 * @param {?} node
5858 * @return {?}
5859 */
5860 node => {
5861 if (replacePostStylesAsPre(node, allPreStyleElements, allPostStyleElements)) {
5862 replaceNodes.push(node);
5863 }
5864 }));
5865 // PRE STAGE: fill the ! styles
5866 /** @type {?} */
5867 const preStylesMap = new Map();
5868 enterNodeMap.forEach((/**
5869 * @param {?} nodes
5870 * @param {?} root
5871 * @return {?}
5872 */
5873 (nodes, root) => {
5874 cloakAndComputeStyles(preStylesMap, this.driver, new Set(nodes), allPreStyleElements, ɵPRE_STYLE);
5875 }));
5876 replaceNodes.forEach((/**
5877 * @param {?} node
5878 * @return {?}
5879 */
5880 node => {
5881 /** @type {?} */
5882 const post = postStylesMap.get(node);
5883 /** @type {?} */
5884 const pre = preStylesMap.get(node);
5885 postStylesMap.set(node, (/** @type {?} */ (Object.assign(Object.assign({}, post), pre))));
5886 }));
5887 /** @type {?} */
5888 const rootPlayers = [];
5889 /** @type {?} */
5890 const subPlayers = [];
5891 /** @type {?} */
5892 const NO_PARENT_ANIMATION_ELEMENT_DETECTED = {};
5893 queuedInstructions.forEach((/**
5894 * @param {?} entry
5895 * @return {?}
5896 */
5897 entry => {
5898 const { element, player, instruction } = entry;
5899 // this means that it was never consumed by a parent animation which
5900 // means that it is independent and therefore should be set for animation
5901 if (subTimelines.has(element)) {
5902 if (disabledElementsSet.has(element)) {
5903 player.onDestroy((/**
5904 * @return {?}
5905 */
5906 () => setStyles(element, instruction.toStyles)));
5907 player.disabled = true;
5908 player.overrideTotalTime(instruction.totalTime);
5909 skippedPlayers.push(player);
5910 return;
5911 }
5912 // this will flow up the DOM and query the map to figure out
5913 // if a parent animation has priority over it. In the situation
5914 // that a parent is detected then it will cancel the loop. If
5915 // nothing is detected, or it takes a few hops to find a parent,
5916 // then it will fill in the missing nodes and signal them as having
5917 // a detected parent (or a NO_PARENT value via a special constant).
5918 /** @type {?} */
5919 let parentWithAnimation = NO_PARENT_ANIMATION_ELEMENT_DETECTED;
5920 if (animationElementMap.size > 1) {
5921 /** @type {?} */
5922 let elm = element;
5923 /** @type {?} */
5924 const parentsToAdd = [];
5925 while (elm = elm.parentNode) {
5926 /** @type {?} */
5927 const detectedParent = animationElementMap.get(elm);
5928 if (detectedParent) {
5929 parentWithAnimation = detectedParent;
5930 break;
5931 }
5932 parentsToAdd.push(elm);
5933 }
5934 parentsToAdd.forEach((/**
5935 * @param {?} parent
5936 * @return {?}
5937 */
5938 parent => animationElementMap.set(parent, parentWithAnimation)));
5939 }
5940 /** @type {?} */
5941 const innerPlayer = this._buildAnimation(player.namespaceId, instruction, allPreviousPlayersMap, skippedPlayersMap, preStylesMap, postStylesMap);
5942 player.setRealPlayer(innerPlayer);
5943 if (parentWithAnimation === NO_PARENT_ANIMATION_ELEMENT_DETECTED) {
5944 rootPlayers.push(player);
5945 }
5946 else {
5947 /** @type {?} */
5948 const parentPlayers = this.playersByElement.get(parentWithAnimation);
5949 if (parentPlayers && parentPlayers.length) {
5950 player.parentPlayer = optimizeGroupPlayer(parentPlayers);
5951 }
5952 skippedPlayers.push(player);
5953 }
5954 }
5955 else {
5956 eraseStyles(element, instruction.fromStyles);
5957 player.onDestroy((/**
5958 * @return {?}
5959 */
5960 () => setStyles(element, instruction.toStyles)));
5961 // there still might be a ancestor player animating this
5962 // element therefore we will still add it as a sub player
5963 // even if its animation may be disabled
5964 subPlayers.push(player);
5965 if (disabledElementsSet.has(element)) {
5966 skippedPlayers.push(player);
5967 }
5968 }
5969 }));
5970 // find all of the sub players' corresponding inner animation player
5971 subPlayers.forEach((/**
5972 * @param {?} player
5973 * @return {?}
5974 */
5975 player => {
5976 // even if any players are not found for a sub animation then it
5977 // will still complete itself after the next tick since it's Noop
5978 /** @type {?} */
5979 const playersForElement = skippedPlayersMap.get(player.element);
5980 if (playersForElement && playersForElement.length) {
5981 /** @type {?} */
5982 const innerPlayer = optimizeGroupPlayer(playersForElement);
5983 player.setRealPlayer(innerPlayer);
5984 }
5985 }));
5986 // the reason why we don't actually play the animation is
5987 // because all that a skipped player is designed to do is to
5988 // fire the start/done transition callback events
5989 skippedPlayers.forEach((/**
5990 * @param {?} player
5991 * @return {?}
5992 */
5993 player => {
5994 if (player.parentPlayer) {
5995 player.syncPlayerEvents(player.parentPlayer);
5996 }
5997 else {
5998 player.destroy();
5999 }
6000 }));
6001 // run through all of the queued removals and see if they
6002 // were picked up by a query. If not then perform the removal
6003 // operation right away unless a parent animation is ongoing.
6004 for (let i = 0; i < allLeaveNodes.length; i++) {
6005 /** @type {?} */
6006 const element = allLeaveNodes[i];
6007 /** @type {?} */
6008 const details = (/** @type {?} */ (element[REMOVAL_FLAG]));
6009 removeClass(element, LEAVE_CLASSNAME);
6010 // this means the element has a removal animation that is being
6011 // taken care of and therefore the inner elements will hang around
6012 // until that animation is over (or the parent queried animation)
6013 if (details && details.hasAnimation)
6014 continue;
6015 /** @type {?} */
6016 let players = [];
6017 // if this element is queried or if it contains queried children
6018 // then we want for the element not to be removed from the page
6019 // until the queried animations have finished
6020 if (queriedElements.size) {
6021 /** @type {?} */
6022 let queriedPlayerResults = queriedElements.get(element);
6023 if (queriedPlayerResults && queriedPlayerResults.length) {
6024 players.push(...queriedPlayerResults);
6025 }
6026 /** @type {?} */
6027 let queriedInnerElements = this.driver.query(element, NG_ANIMATING_SELECTOR, true);
6028 for (let j = 0; j < queriedInnerElements.length; j++) {
6029 /** @type {?} */
6030 let queriedPlayers = queriedElements.get(queriedInnerElements[j]);
6031 if (queriedPlayers && queriedPlayers.length) {
6032 players.push(...queriedPlayers);
6033 }
6034 }
6035 }
6036 /** @type {?} */
6037 const activePlayers = players.filter((/**
6038 * @param {?} p
6039 * @return {?}
6040 */
6041 p => !p.destroyed));
6042 if (activePlayers.length) {
6043 removeNodesAfterAnimationDone(this, element, activePlayers);
6044 }
6045 else {
6046 this.processLeaveNode(element);
6047 }
6048 }
6049 // this is required so the cleanup method doesn't remove them
6050 allLeaveNodes.length = 0;
6051 rootPlayers.forEach((/**
6052 * @param {?} player
6053 * @return {?}
6054 */
6055 player => {
6056 this.players.push(player);
6057 player.onDone((/**
6058 * @return {?}
6059 */
6060 () => {
6061 player.destroy();
6062 /** @type {?} */
6063 const index = this.players.indexOf(player);
6064 this.players.splice(index, 1);
6065 }));
6066 player.play();
6067 }));
6068 return rootPlayers;
6069 }
6070 /**
6071 * @param {?} namespaceId
6072 * @param {?} element
6073 * @return {?}
6074 */
6075 elementContainsData(namespaceId, element) {
6076 /** @type {?} */
6077 let containsData = false;
6078 /** @type {?} */
6079 const details = (/** @type {?} */ (element[REMOVAL_FLAG]));
6080 if (details && details.setForRemoval)
6081 containsData = true;
6082 if (this.playersByElement.has(element))
6083 containsData = true;
6084 if (this.playersByQueriedElement.has(element))
6085 containsData = true;
6086 if (this.statesByElement.has(element))
6087 containsData = true;
6088 return this._fetchNamespace(namespaceId).elementContainsData(element) || containsData;
6089 }
6090 /**
6091 * @param {?} callback
6092 * @return {?}
6093 */
6094 afterFlush(callback) { this._flushFns.push(callback); }
6095 /**
6096 * @param {?} callback
6097 * @return {?}
6098 */
6099 afterFlushAnimationsDone(callback) { this._whenQuietFns.push(callback); }
6100 /**
6101 * @private
6102 * @param {?} element
6103 * @param {?} isQueriedElement
6104 * @param {?=} namespaceId
6105 * @param {?=} triggerName
6106 * @param {?=} toStateValue
6107 * @return {?}
6108 */
6109 _getPreviousPlayers(element, isQueriedElement, namespaceId, triggerName, toStateValue) {
6110 /** @type {?} */
6111 let players = [];
6112 if (isQueriedElement) {
6113 /** @type {?} */
6114 const queriedElementPlayers = this.playersByQueriedElement.get(element);
6115 if (queriedElementPlayers) {
6116 players = queriedElementPlayers;
6117 }
6118 }
6119 else {
6120 /** @type {?} */
6121 const elementPlayers = this.playersByElement.get(element);
6122 if (elementPlayers) {
6123 /** @type {?} */
6124 const isRemovalAnimation = !toStateValue || toStateValue == VOID_VALUE;
6125 elementPlayers.forEach((/**
6126 * @param {?} player
6127 * @return {?}
6128 */
6129 player => {
6130 if (player.queued)
6131 return;
6132 if (!isRemovalAnimation && player.triggerName != triggerName)
6133 return;
6134 players.push(player);
6135 }));
6136 }
6137 }
6138 if (namespaceId || triggerName) {
6139 players = players.filter((/**
6140 * @param {?} player
6141 * @return {?}
6142 */
6143 player => {
6144 if (namespaceId && namespaceId != player.namespaceId)
6145 return false;
6146 if (triggerName && triggerName != player.triggerName)
6147 return false;
6148 return true;
6149 }));
6150 }
6151 return players;
6152 }
6153 /**
6154 * @private
6155 * @param {?} namespaceId
6156 * @param {?} instruction
6157 * @param {?} allPreviousPlayersMap
6158 * @return {?}
6159 */
6160 _beforeAnimationBuild(namespaceId, instruction, allPreviousPlayersMap) {
6161 /** @type {?} */
6162 const triggerName = instruction.triggerName;
6163 /** @type {?} */
6164 const rootElement = instruction.element;
6165 // when a removal animation occurs, ALL previous players are collected
6166 // and destroyed (even if they are outside of the current namespace)
6167 /** @type {?} */
6168 const targetNameSpaceId = instruction.isRemovalTransition ? undefined : namespaceId;
6169 /** @type {?} */
6170 const targetTriggerName = instruction.isRemovalTransition ? undefined : triggerName;
6171 for (const timelineInstruction of instruction.timelines) {
6172 /** @type {?} */
6173 const element = timelineInstruction.element;
6174 /** @type {?} */
6175 const isQueriedElement = element !== rootElement;
6176 /** @type {?} */
6177 const players = getOrSetAsInMap(allPreviousPlayersMap, element, []);
6178 /** @type {?} */
6179 const previousPlayers = this._getPreviousPlayers(element, isQueriedElement, targetNameSpaceId, targetTriggerName, instruction.toState);
6180 previousPlayers.forEach((/**
6181 * @param {?} player
6182 * @return {?}
6183 */
6184 player => {
6185 /** @type {?} */
6186 const realPlayer = (/** @type {?} */ (((/** @type {?} */ (player))).getRealPlayer()));
6187 if (realPlayer.beforeDestroy) {
6188 realPlayer.beforeDestroy();
6189 }
6190 player.destroy();
6191 players.push(player);
6192 }));
6193 }
6194 // this needs to be done so that the PRE/POST styles can be
6195 // computed properly without interfering with the previous animation
6196 eraseStyles(rootElement, instruction.fromStyles);
6197 }
6198 /**
6199 * @private
6200 * @param {?} namespaceId
6201 * @param {?} instruction
6202 * @param {?} allPreviousPlayersMap
6203 * @param {?} skippedPlayersMap
6204 * @param {?} preStylesMap
6205 * @param {?} postStylesMap
6206 * @return {?}
6207 */
6208 _buildAnimation(namespaceId, instruction, allPreviousPlayersMap, skippedPlayersMap, preStylesMap, postStylesMap) {
6209 /** @type {?} */
6210 const triggerName = instruction.triggerName;
6211 /** @type {?} */
6212 const rootElement = instruction.element;
6213 // we first run this so that the previous animation player
6214 // data can be passed into the successive animation players
6215 /** @type {?} */
6216 const allQueriedPlayers = [];
6217 /** @type {?} */
6218 const allConsumedElements = new Set();
6219 /** @type {?} */
6220 const allSubElements = new Set();
6221 /** @type {?} */
6222 const allNewPlayers = instruction.timelines.map((/**
6223 * @param {?} timelineInstruction
6224 * @return {?}
6225 */
6226 timelineInstruction => {
6227 /** @type {?} */
6228 const element = timelineInstruction.element;
6229 allConsumedElements.add(element);
6230 // FIXME (matsko): make sure to-be-removed animations are removed properly
6231 /** @type {?} */
6232 const details = element[REMOVAL_FLAG];
6233 if (details && details.removedBeforeQueried)
6234 return new NoopAnimationPlayer(timelineInstruction.duration, timelineInstruction.delay);
6235 /** @type {?} */
6236 const isQueriedElement = element !== rootElement;
6237 /** @type {?} */
6238 const previousPlayers = flattenGroupPlayers((allPreviousPlayersMap.get(element) || EMPTY_PLAYER_ARRAY)
6239 .map((/**
6240 * @param {?} p
6241 * @return {?}
6242 */
6243 p => p.getRealPlayer())))
6244 .filter((/**
6245 * @param {?} p
6246 * @return {?}
6247 */
6248 p => {
6249 // the `element` is not apart of the AnimationPlayer definition, but
6250 // Mock/WebAnimations
6251 // use the element within their implementation. This will be added in Angular5 to
6252 // AnimationPlayer
6253 /** @type {?} */
6254 const pp = (/** @type {?} */ (p));
6255 return pp.element ? pp.element === element : false;
6256 }));
6257 /** @type {?} */
6258 const preStyles = preStylesMap.get(element);
6259 /** @type {?} */
6260 const postStyles = postStylesMap.get(element);
6261 /** @type {?} */
6262 const keyframes = normalizeKeyframes(this.driver, this._normalizer, element, timelineInstruction.keyframes, preStyles, postStyles);
6263 /** @type {?} */
6264 const player = this._buildPlayer(timelineInstruction, keyframes, previousPlayers);
6265 // this means that this particular player belongs to a sub trigger. It is
6266 // important that we match this player up with the corresponding (@trigger.listener)
6267 if (timelineInstruction.subTimeline && skippedPlayersMap) {
6268 allSubElements.add(element);
6269 }
6270 if (isQueriedElement) {
6271 /** @type {?} */
6272 const wrappedPlayer = new TransitionAnimationPlayer(namespaceId, triggerName, element);
6273 wrappedPlayer.setRealPlayer(player);
6274 allQueriedPlayers.push(wrappedPlayer);
6275 }
6276 return player;
6277 }));
6278 allQueriedPlayers.forEach((/**
6279 * @param {?} player
6280 * @return {?}
6281 */
6282 player => {
6283 getOrSetAsInMap(this.playersByQueriedElement, player.element, []).push(player);
6284 player.onDone((/**
6285 * @return {?}
6286 */
6287 () => deleteOrUnsetInMap(this.playersByQueriedElement, player.element, player)));
6288 }));
6289 allConsumedElements.forEach((/**
6290 * @param {?} element
6291 * @return {?}
6292 */
6293 element => addClass(element, NG_ANIMATING_CLASSNAME)));
6294 /** @type {?} */
6295 const player = optimizeGroupPlayer(allNewPlayers);
6296 player.onDestroy((/**
6297 * @return {?}
6298 */
6299 () => {
6300 allConsumedElements.forEach((/**
6301 * @param {?} element
6302 * @return {?}
6303 */
6304 element => removeClass(element, NG_ANIMATING_CLASSNAME)));
6305 setStyles(rootElement, instruction.toStyles);
6306 }));
6307 // this basically makes all of the callbacks for sub element animations
6308 // be dependent on the upper players for when they finish
6309 allSubElements.forEach((/**
6310 * @param {?} element
6311 * @return {?}
6312 */
6313 element => { getOrSetAsInMap(skippedPlayersMap, element, []).push(player); }));
6314 return player;
6315 }
6316 /**
6317 * @private
6318 * @param {?} instruction
6319 * @param {?} keyframes
6320 * @param {?} previousPlayers
6321 * @return {?}
6322 */
6323 _buildPlayer(instruction, keyframes, previousPlayers) {
6324 if (keyframes.length > 0) {
6325 return this.driver.animate(instruction.element, keyframes, instruction.duration, instruction.delay, instruction.easing, previousPlayers);
6326 }
6327 // special case for when an empty transition|definition is provided
6328 // ... there is no point in rendering an empty animation
6329 return new NoopAnimationPlayer(instruction.duration, instruction.delay);
6330 }
6331}
6332if (false) {
6333 /** @type {?} */
6334 TransitionAnimationEngine.prototype.players;
6335 /** @type {?} */
6336 TransitionAnimationEngine.prototype.newHostElements;
6337 /** @type {?} */
6338 TransitionAnimationEngine.prototype.playersByElement;
6339 /** @type {?} */
6340 TransitionAnimationEngine.prototype.playersByQueriedElement;
6341 /** @type {?} */
6342 TransitionAnimationEngine.prototype.statesByElement;
6343 /** @type {?} */
6344 TransitionAnimationEngine.prototype.disabledNodes;
6345 /** @type {?} */
6346 TransitionAnimationEngine.prototype.totalAnimations;
6347 /** @type {?} */
6348 TransitionAnimationEngine.prototype.totalQueuedPlayers;
6349 /**
6350 * @type {?}
6351 * @private
6352 */
6353 TransitionAnimationEngine.prototype._namespaceLookup;
6354 /**
6355 * @type {?}
6356 * @private
6357 */
6358 TransitionAnimationEngine.prototype._namespaceList;
6359 /**
6360 * @type {?}
6361 * @private
6362 */
6363 TransitionAnimationEngine.prototype._flushFns;
6364 /**
6365 * @type {?}
6366 * @private
6367 */
6368 TransitionAnimationEngine.prototype._whenQuietFns;
6369 /** @type {?} */
6370 TransitionAnimationEngine.prototype.namespacesByHostElement;
6371 /** @type {?} */
6372 TransitionAnimationEngine.prototype.collectedEnterElements;
6373 /** @type {?} */
6374 TransitionAnimationEngine.prototype.collectedLeaveElements;
6375 /** @type {?} */
6376 TransitionAnimationEngine.prototype.onRemovalComplete;
6377 /** @type {?} */
6378 TransitionAnimationEngine.prototype.bodyNode;
6379 /** @type {?} */
6380 TransitionAnimationEngine.prototype.driver;
6381 /**
6382 * @type {?}
6383 * @private
6384 */
6385 TransitionAnimationEngine.prototype._normalizer;
6386}
6387class TransitionAnimationPlayer {
6388 /**
6389 * @param {?} namespaceId
6390 * @param {?} triggerName
6391 * @param {?} element
6392 */
6393 constructor(namespaceId, triggerName, element) {
6394 this.namespaceId = namespaceId;
6395 this.triggerName = triggerName;
6396 this.element = element;
6397 this._player = new NoopAnimationPlayer();
6398 this._containsRealPlayer = false;
6399 this._queuedCallbacks = {};
6400 this.destroyed = false;
6401 this.markedForDestroy = false;
6402 this.disabled = false;
6403 this.queued = true;
6404 this.totalTime = 0;
6405 }
6406 /**
6407 * @param {?} player
6408 * @return {?}
6409 */
6410 setRealPlayer(player) {
6411 if (this._containsRealPlayer)
6412 return;
6413 this._player = player;
6414 Object.keys(this._queuedCallbacks).forEach((/**
6415 * @param {?} phase
6416 * @return {?}
6417 */
6418 phase => {
6419 this._queuedCallbacks[phase].forEach((/**
6420 * @param {?} callback
6421 * @return {?}
6422 */
6423 callback => listenOnPlayer(player, phase, undefined, callback)));
6424 }));
6425 this._queuedCallbacks = {};
6426 this._containsRealPlayer = true;
6427 this.overrideTotalTime(player.totalTime);
6428 ((/** @type {?} */ (this))).queued = false;
6429 }
6430 /**
6431 * @return {?}
6432 */
6433 getRealPlayer() { return this._player; }
6434 /**
6435 * @param {?} totalTime
6436 * @return {?}
6437 */
6438 overrideTotalTime(totalTime) { ((/** @type {?} */ (this))).totalTime = totalTime; }
6439 /**
6440 * @param {?} player
6441 * @return {?}
6442 */
6443 syncPlayerEvents(player) {
6444 /** @type {?} */
6445 const p = (/** @type {?} */ (this._player));
6446 if (p.triggerCallback) {
6447 player.onStart((/**
6448 * @return {?}
6449 */
6450 () => (/** @type {?} */ (p.triggerCallback))('start')));
6451 }
6452 player.onDone((/**
6453 * @return {?}
6454 */
6455 () => this.finish()));
6456 player.onDestroy((/**
6457 * @return {?}
6458 */
6459 () => this.destroy()));
6460 }
6461 /**
6462 * @private
6463 * @param {?} name
6464 * @param {?} callback
6465 * @return {?}
6466 */
6467 _queueEvent(name, callback) {
6468 getOrSetAsInMap(this._queuedCallbacks, name, []).push(callback);
6469 }
6470 /**
6471 * @param {?} fn
6472 * @return {?}
6473 */
6474 onDone(fn) {
6475 if (this.queued) {
6476 this._queueEvent('done', fn);
6477 }
6478 this._player.onDone(fn);
6479 }
6480 /**
6481 * @param {?} fn
6482 * @return {?}
6483 */
6484 onStart(fn) {
6485 if (this.queued) {
6486 this._queueEvent('start', fn);
6487 }
6488 this._player.onStart(fn);
6489 }
6490 /**
6491 * @param {?} fn
6492 * @return {?}
6493 */
6494 onDestroy(fn) {
6495 if (this.queued) {
6496 this._queueEvent('destroy', fn);
6497 }
6498 this._player.onDestroy(fn);
6499 }
6500 /**
6501 * @return {?}
6502 */
6503 init() { this._player.init(); }
6504 /**
6505 * @return {?}
6506 */
6507 hasStarted() { return this.queued ? false : this._player.hasStarted(); }
6508 /**
6509 * @return {?}
6510 */
6511 play() { !this.queued && this._player.play(); }
6512 /**
6513 * @return {?}
6514 */
6515 pause() { !this.queued && this._player.pause(); }
6516 /**
6517 * @return {?}
6518 */
6519 restart() { !this.queued && this._player.restart(); }
6520 /**
6521 * @return {?}
6522 */
6523 finish() { this._player.finish(); }
6524 /**
6525 * @return {?}
6526 */
6527 destroy() {
6528 ((/** @type {?} */ (this))).destroyed = true;
6529 this._player.destroy();
6530 }
6531 /**
6532 * @return {?}
6533 */
6534 reset() { !this.queued && this._player.reset(); }
6535 /**
6536 * @param {?} p
6537 * @return {?}
6538 */
6539 setPosition(p) {
6540 if (!this.queued) {
6541 this._player.setPosition(p);
6542 }
6543 }
6544 /**
6545 * @return {?}
6546 */
6547 getPosition() { return this.queued ? 0 : this._player.getPosition(); }
6548 /**
6549 * \@internal
6550 * @param {?} phaseName
6551 * @return {?}
6552 */
6553 triggerCallback(phaseName) {
6554 /** @type {?} */
6555 const p = (/** @type {?} */ (this._player));
6556 if (p.triggerCallback) {
6557 p.triggerCallback(phaseName);
6558 }
6559 }
6560}
6561if (false) {
6562 /**
6563 * @type {?}
6564 * @private
6565 */
6566 TransitionAnimationPlayer.prototype._player;
6567 /**
6568 * @type {?}
6569 * @private
6570 */
6571 TransitionAnimationPlayer.prototype._containsRealPlayer;
6572 /**
6573 * @type {?}
6574 * @private
6575 */
6576 TransitionAnimationPlayer.prototype._queuedCallbacks;
6577 /** @type {?} */
6578 TransitionAnimationPlayer.prototype.destroyed;
6579 /** @type {?} */
6580 TransitionAnimationPlayer.prototype.parentPlayer;
6581 /** @type {?} */
6582 TransitionAnimationPlayer.prototype.markedForDestroy;
6583 /** @type {?} */
6584 TransitionAnimationPlayer.prototype.disabled;
6585 /** @type {?} */
6586 TransitionAnimationPlayer.prototype.queued;
6587 /** @type {?} */
6588 TransitionAnimationPlayer.prototype.totalTime;
6589 /** @type {?} */
6590 TransitionAnimationPlayer.prototype.namespaceId;
6591 /** @type {?} */
6592 TransitionAnimationPlayer.prototype.triggerName;
6593 /** @type {?} */
6594 TransitionAnimationPlayer.prototype.element;
6595}
6596/**
6597 * @param {?} map
6598 * @param {?} key
6599 * @param {?} value
6600 * @return {?}
6601 */
6602function deleteOrUnsetInMap(map, key, value) {
6603 /** @type {?} */
6604 let currentValues;
6605 if (map instanceof Map) {
6606 currentValues = map.get(key);
6607 if (currentValues) {
6608 if (currentValues.length) {
6609 /** @type {?} */
6610 const index = currentValues.indexOf(value);
6611 currentValues.splice(index, 1);
6612 }
6613 if (currentValues.length == 0) {
6614 map.delete(key);
6615 }
6616 }
6617 }
6618 else {
6619 currentValues = map[key];
6620 if (currentValues) {
6621 if (currentValues.length) {
6622 /** @type {?} */
6623 const index = currentValues.indexOf(value);
6624 currentValues.splice(index, 1);
6625 }
6626 if (currentValues.length == 0) {
6627 delete map[key];
6628 }
6629 }
6630 }
6631 return currentValues;
6632}
6633/**
6634 * @param {?} value
6635 * @return {?}
6636 */
6637function normalizeTriggerValue(value) {
6638 // we use `!= null` here because it's the most simple
6639 // way to test against a "falsy" value without mixing
6640 // in empty strings or a zero value. DO NOT OPTIMIZE.
6641 return value != null ? value : null;
6642}
6643/**
6644 * @param {?} node
6645 * @return {?}
6646 */
6647function isElementNode(node) {
6648 return node && node['nodeType'] === 1;
6649}
6650/**
6651 * @param {?} eventName
6652 * @return {?}
6653 */
6654function isTriggerEventValid(eventName) {
6655 return eventName == 'start' || eventName == 'done';
6656}
6657/**
6658 * @param {?} element
6659 * @param {?=} value
6660 * @return {?}
6661 */
6662function cloakElement(element, value) {
6663 /** @type {?} */
6664 const oldValue = element.style.display;
6665 element.style.display = value != null ? value : 'none';
6666 return oldValue;
6667}
6668/**
6669 * @param {?} valuesMap
6670 * @param {?} driver
6671 * @param {?} elements
6672 * @param {?} elementPropsMap
6673 * @param {?} defaultStyle
6674 * @return {?}
6675 */
6676function cloakAndComputeStyles(valuesMap, driver, elements, elementPropsMap, defaultStyle) {
6677 /** @type {?} */
6678 const cloakVals = [];
6679 elements.forEach((/**
6680 * @param {?} element
6681 * @return {?}
6682 */
6683 element => cloakVals.push(cloakElement(element))));
6684 /** @type {?} */
6685 const failedElements = [];
6686 elementPropsMap.forEach((/**
6687 * @param {?} props
6688 * @param {?} element
6689 * @return {?}
6690 */
6691 (props, element) => {
6692 /** @type {?} */
6693 const styles = {};
6694 props.forEach((/**
6695 * @param {?} prop
6696 * @return {?}
6697 */
6698 prop => {
6699 /** @type {?} */
6700 const value = styles[prop] = driver.computeStyle(element, prop, defaultStyle);
6701 // there is no easy way to detect this because a sub element could be removed
6702 // by a parent animation element being detached.
6703 if (!value || value.length == 0) {
6704 element[REMOVAL_FLAG] = NULL_REMOVED_QUERIED_STATE;
6705 failedElements.push(element);
6706 }
6707 }));
6708 valuesMap.set(element, styles);
6709 }));
6710 // we use a index variable here since Set.forEach(a, i) does not return
6711 // an index value for the closure (but instead just the value)
6712 /** @type {?} */
6713 let i = 0;
6714 elements.forEach((/**
6715 * @param {?} element
6716 * @return {?}
6717 */
6718 element => cloakElement(element, cloakVals[i++])));
6719 return failedElements;
6720}
6721/*
6722Since the Angular renderer code will return a collection of inserted
6723nodes in all areas of a DOM tree, it's up to this algorithm to figure
6724out which nodes are roots for each animation @trigger.
6725
6726By placing each inserted node into a Set and traversing upwards, it
6727is possible to find the @trigger elements and well any direct *star
6728insertion nodes, if a @trigger root is found then the enter element
6729is placed into the Map[@trigger] spot.
6730 */
6731/**
6732 * @param {?} roots
6733 * @param {?} nodes
6734 * @return {?}
6735 */
6736function buildRootMap(roots, nodes) {
6737 /** @type {?} */
6738 const rootMap = new Map();
6739 roots.forEach((/**
6740 * @param {?} root
6741 * @return {?}
6742 */
6743 root => rootMap.set(root, [])));
6744 if (nodes.length == 0)
6745 return rootMap;
6746 /** @type {?} */
6747 const NULL_NODE = 1;
6748 /** @type {?} */
6749 const nodeSet = new Set(nodes);
6750 /** @type {?} */
6751 const localRootMap = new Map();
6752 /**
6753 * @param {?} node
6754 * @return {?}
6755 */
6756 function getRoot(node) {
6757 if (!node)
6758 return NULL_NODE;
6759 /** @type {?} */
6760 let root = localRootMap.get(node);
6761 if (root)
6762 return root;
6763 /** @type {?} */
6764 const parent = node.parentNode;
6765 if (rootMap.has(parent)) { // ngIf inside @trigger
6766 root = parent;
6767 }
6768 else if (nodeSet.has(parent)) { // ngIf inside ngIf
6769 root = NULL_NODE;
6770 }
6771 else { // recurse upwards
6772 root = getRoot(parent);
6773 }
6774 localRootMap.set(node, root);
6775 return root;
6776 }
6777 nodes.forEach((/**
6778 * @param {?} node
6779 * @return {?}
6780 */
6781 node => {
6782 /** @type {?} */
6783 const root = getRoot(node);
6784 if (root !== NULL_NODE) {
6785 (/** @type {?} */ (rootMap.get(root))).push(node);
6786 }
6787 }));
6788 return rootMap;
6789}
6790/** @type {?} */
6791const CLASSES_CACHE_KEY = '$$classes';
6792/**
6793 * @param {?} element
6794 * @param {?} className
6795 * @return {?}
6796 */
6797function containsClass(element, className) {
6798 if (element.classList) {
6799 return element.classList.contains(className);
6800 }
6801 else {
6802 /** @type {?} */
6803 const classes = element[CLASSES_CACHE_KEY];
6804 return classes && classes[className];
6805 }
6806}
6807/**
6808 * @param {?} element
6809 * @param {?} className
6810 * @return {?}
6811 */
6812function addClass(element, className) {
6813 if (element.classList) {
6814 element.classList.add(className);
6815 }
6816 else {
6817 /** @type {?} */
6818 let classes = element[CLASSES_CACHE_KEY];
6819 if (!classes) {
6820 classes = element[CLASSES_CACHE_KEY] = {};
6821 }
6822 classes[className] = true;
6823 }
6824}
6825/**
6826 * @param {?} element
6827 * @param {?} className
6828 * @return {?}
6829 */
6830function removeClass(element, className) {
6831 if (element.classList) {
6832 element.classList.remove(className);
6833 }
6834 else {
6835 /** @type {?} */
6836 let classes = element[CLASSES_CACHE_KEY];
6837 if (classes) {
6838 delete classes[className];
6839 }
6840 }
6841}
6842/**
6843 * @param {?} engine
6844 * @param {?} element
6845 * @param {?} players
6846 * @return {?}
6847 */
6848function removeNodesAfterAnimationDone(engine, element, players) {
6849 optimizeGroupPlayer(players).onDone((/**
6850 * @return {?}
6851 */
6852 () => engine.processLeaveNode(element)));
6853}
6854/**
6855 * @param {?} players
6856 * @return {?}
6857 */
6858function flattenGroupPlayers(players) {
6859 /** @type {?} */
6860 const finalPlayers = [];
6861 _flattenGroupPlayersRecur(players, finalPlayers);
6862 return finalPlayers;
6863}
6864/**
6865 * @param {?} players
6866 * @param {?} finalPlayers
6867 * @return {?}
6868 */
6869function _flattenGroupPlayersRecur(players, finalPlayers) {
6870 for (let i = 0; i < players.length; i++) {
6871 /** @type {?} */
6872 const player = players[i];
6873 if (player instanceof ɵAnimationGroupPlayer) {
6874 _flattenGroupPlayersRecur(player.players, finalPlayers);
6875 }
6876 else {
6877 finalPlayers.push(player);
6878 }
6879 }
6880}
6881/**
6882 * @param {?} a
6883 * @param {?} b
6884 * @return {?}
6885 */
6886function objEquals(a, b) {
6887 /** @type {?} */
6888 const k1 = Object.keys(a);
6889 /** @type {?} */
6890 const k2 = Object.keys(b);
6891 if (k1.length != k2.length)
6892 return false;
6893 for (let i = 0; i < k1.length; i++) {
6894 /** @type {?} */
6895 const prop = k1[i];
6896 if (!b.hasOwnProperty(prop) || a[prop] !== b[prop])
6897 return false;
6898 }
6899 return true;
6900}
6901/**
6902 * @param {?} element
6903 * @param {?} allPreStyleElements
6904 * @param {?} allPostStyleElements
6905 * @return {?}
6906 */
6907function replacePostStylesAsPre(element, allPreStyleElements, allPostStyleElements) {
6908 /** @type {?} */
6909 const postEntry = allPostStyleElements.get(element);
6910 if (!postEntry)
6911 return false;
6912 /** @type {?} */
6913 let preEntry = allPreStyleElements.get(element);
6914 if (preEntry) {
6915 postEntry.forEach((/**
6916 * @param {?} data
6917 * @return {?}
6918 */
6919 data => (/** @type {?} */ (preEntry)).add(data)));
6920 }
6921 else {
6922 allPreStyleElements.set(element, postEntry);
6923 }
6924 allPostStyleElements.delete(element);
6925 return true;
6926}
6927
6928/**
6929 * @fileoverview added by tsickle
6930 * Generated from: packages/animations/browser/src/render/animation_engine_next.ts
6931 * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
6932 */
6933class AnimationEngine {
6934 /**
6935 * @param {?} bodyNode
6936 * @param {?} _driver
6937 * @param {?} normalizer
6938 */
6939 constructor(bodyNode, _driver, normalizer) {
6940 this.bodyNode = bodyNode;
6941 this._driver = _driver;
6942 this._triggerCache = {};
6943 // this method is designed to be overridden by the code that uses this engine
6944 this.onRemovalComplete = (/**
6945 * @param {?} element
6946 * @param {?} context
6947 * @return {?}
6948 */
6949 (element, context) => { });
6950 this._transitionEngine = new TransitionAnimationEngine(bodyNode, _driver, normalizer);
6951 this._timelineEngine = new TimelineAnimationEngine(bodyNode, _driver, normalizer);
6952 this._transitionEngine.onRemovalComplete = (/**
6953 * @param {?} element
6954 * @param {?} context
6955 * @return {?}
6956 */
6957 (element, context) => this.onRemovalComplete(element, context));
6958 }
6959 /**
6960 * @param {?} componentId
6961 * @param {?} namespaceId
6962 * @param {?} hostElement
6963 * @param {?} name
6964 * @param {?} metadata
6965 * @return {?}
6966 */
6967 registerTrigger(componentId, namespaceId, hostElement, name, metadata) {
6968 /** @type {?} */
6969 const cacheKey = componentId + '-' + name;
6970 /** @type {?} */
6971 let trigger = this._triggerCache[cacheKey];
6972 if (!trigger) {
6973 /** @type {?} */
6974 const errors = [];
6975 /** @type {?} */
6976 const ast = (/** @type {?} */ (buildAnimationAst(this._driver, (/** @type {?} */ (metadata)), errors)));
6977 if (errors.length) {
6978 throw new Error(`The animation trigger "${name}" has failed to build due to the following errors:\n - ${errors.join("\n - ")}`);
6979 }
6980 trigger = buildTrigger(name, ast);
6981 this._triggerCache[cacheKey] = trigger;
6982 }
6983 this._transitionEngine.registerTrigger(namespaceId, name, trigger);
6984 }
6985 /**
6986 * @param {?} namespaceId
6987 * @param {?} hostElement
6988 * @return {?}
6989 */
6990 register(namespaceId, hostElement) {
6991 this._transitionEngine.register(namespaceId, hostElement);
6992 }
6993 /**
6994 * @param {?} namespaceId
6995 * @param {?} context
6996 * @return {?}
6997 */
6998 destroy(namespaceId, context) {
6999 this._transitionEngine.destroy(namespaceId, context);
7000 }
7001 /**
7002 * @param {?} namespaceId
7003 * @param {?} element
7004 * @param {?} parent
7005 * @param {?} insertBefore
7006 * @return {?}
7007 */
7008 onInsert(namespaceId, element, parent, insertBefore) {
7009 this._transitionEngine.insertNode(namespaceId, element, parent, insertBefore);
7010 }
7011 /**
7012 * @param {?} namespaceId
7013 * @param {?} element
7014 * @param {?} context
7015 * @param {?=} isHostElement
7016 * @return {?}
7017 */
7018 onRemove(namespaceId, element, context, isHostElement) {
7019 this._transitionEngine.removeNode(namespaceId, element, isHostElement || false, context);
7020 }
7021 /**
7022 * @param {?} element
7023 * @param {?} disable
7024 * @return {?}
7025 */
7026 disableAnimations(element, disable) {
7027 this._transitionEngine.markElementAsDisabled(element, disable);
7028 }
7029 /**
7030 * @param {?} namespaceId
7031 * @param {?} element
7032 * @param {?} property
7033 * @param {?} value
7034 * @return {?}
7035 */
7036 process(namespaceId, element, property, value) {
7037 if (property.charAt(0) == '@') {
7038 const [id, action] = parseTimelineCommand(property);
7039 /** @type {?} */
7040 const args = (/** @type {?} */ (value));
7041 this._timelineEngine.command(id, element, action, args);
7042 }
7043 else {
7044 this._transitionEngine.trigger(namespaceId, element, property, value);
7045 }
7046 }
7047 /**
7048 * @param {?} namespaceId
7049 * @param {?} element
7050 * @param {?} eventName
7051 * @param {?} eventPhase
7052 * @param {?} callback
7053 * @return {?}
7054 */
7055 listen(namespaceId, element, eventName, eventPhase, callback) {
7056 // @@listen
7057 if (eventName.charAt(0) == '@') {
7058 const [id, action] = parseTimelineCommand(eventName);
7059 return this._timelineEngine.listen(id, element, action, callback);
7060 }
7061 return this._transitionEngine.listen(namespaceId, element, eventName, eventPhase, callback);
7062 }
7063 /**
7064 * @param {?=} microtaskId
7065 * @return {?}
7066 */
7067 flush(microtaskId = -1) { this._transitionEngine.flush(microtaskId); }
7068 /**
7069 * @return {?}
7070 */
7071 get players() {
7072 return ((/** @type {?} */ (this._transitionEngine.players)))
7073 .concat((/** @type {?} */ (this._timelineEngine.players)));
7074 }
7075 /**
7076 * @return {?}
7077 */
7078 whenRenderingDone() { return this._transitionEngine.whenRenderingDone(); }
7079}
7080if (false) {
7081 /**
7082 * @type {?}
7083 * @private
7084 */
7085 AnimationEngine.prototype._transitionEngine;
7086 /**
7087 * @type {?}
7088 * @private
7089 */
7090 AnimationEngine.prototype._timelineEngine;
7091 /**
7092 * @type {?}
7093 * @private
7094 */
7095 AnimationEngine.prototype._triggerCache;
7096 /** @type {?} */
7097 AnimationEngine.prototype.onRemovalComplete;
7098 /**
7099 * @type {?}
7100 * @private
7101 */
7102 AnimationEngine.prototype.bodyNode;
7103 /**
7104 * @type {?}
7105 * @private
7106 */
7107 AnimationEngine.prototype._driver;
7108}
7109
7110/**
7111 * @fileoverview added by tsickle
7112 * Generated from: packages/animations/browser/src/render/special_cased_styles.ts
7113 * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
7114 */
7115/**
7116 * Returns an instance of `SpecialCasedStyles` if and when any special (non animateable) styles are
7117 * detected.
7118 *
7119 * In CSS there exist properties that cannot be animated within a keyframe animation
7120 * (whether it be via CSS keyframes or web-animations) and the animation implementation
7121 * will ignore them. This function is designed to detect those special cased styles and
7122 * return a container that will be executed at the start and end of the animation.
7123 *
7124 * @param {?} element
7125 * @param {?} styles
7126 * @return {?} an instance of `SpecialCasedStyles` if any special styles are detected otherwise `null`
7127 */
7128function packageNonAnimatableStyles(element, styles) {
7129 /** @type {?} */
7130 let startStyles = null;
7131 /** @type {?} */
7132 let endStyles = null;
7133 if (Array.isArray(styles) && styles.length) {
7134 startStyles = filterNonAnimatableStyles(styles[0]);
7135 if (styles.length > 1) {
7136 endStyles = filterNonAnimatableStyles(styles[styles.length - 1]);
7137 }
7138 }
7139 else if (styles) {
7140 startStyles = filterNonAnimatableStyles(styles);
7141 }
7142 return (startStyles || endStyles) ? new SpecialCasedStyles(element, startStyles, endStyles) :
7143 null;
7144}
7145/**
7146 * Designed to be executed during a keyframe-based animation to apply any special-cased styles.
7147 *
7148 * When started (when the `start()` method is run) then the provided `startStyles`
7149 * will be applied. When finished (when the `finish()` method is called) the
7150 * `endStyles` will be applied as well any any starting styles. Finally when
7151 * `destroy()` is called then all styles will be removed.
7152 */
7153class SpecialCasedStyles {
7154 /**
7155 * @param {?} _element
7156 * @param {?} _startStyles
7157 * @param {?} _endStyles
7158 */
7159 constructor(_element, _startStyles, _endStyles) {
7160 this._element = _element;
7161 this._startStyles = _startStyles;
7162 this._endStyles = _endStyles;
7163 this._state = 0 /* Pending */;
7164 /** @type {?} */
7165 let initialStyles = SpecialCasedStyles.initialStylesByElement.get(_element);
7166 if (!initialStyles) {
7167 SpecialCasedStyles.initialStylesByElement.set(_element, initialStyles = {});
7168 }
7169 this._initialStyles = initialStyles;
7170 }
7171 /**
7172 * @return {?}
7173 */
7174 start() {
7175 if (this._state < 1 /* Started */) {
7176 if (this._startStyles) {
7177 setStyles(this._element, this._startStyles, this._initialStyles);
7178 }
7179 this._state = 1 /* Started */;
7180 }
7181 }
7182 /**
7183 * @return {?}
7184 */
7185 finish() {
7186 this.start();
7187 if (this._state < 2 /* Finished */) {
7188 setStyles(this._element, this._initialStyles);
7189 if (this._endStyles) {
7190 setStyles(this._element, this._endStyles);
7191 this._endStyles = null;
7192 }
7193 this._state = 1 /* Started */;
7194 }
7195 }
7196 /**
7197 * @return {?}
7198 */
7199 destroy() {
7200 this.finish();
7201 if (this._state < 3 /* Destroyed */) {
7202 SpecialCasedStyles.initialStylesByElement.delete(this._element);
7203 if (this._startStyles) {
7204 eraseStyles(this._element, this._startStyles);
7205 this._endStyles = null;
7206 }
7207 if (this._endStyles) {
7208 eraseStyles(this._element, this._endStyles);
7209 this._endStyles = null;
7210 }
7211 setStyles(this._element, this._initialStyles);
7212 this._state = 3 /* Destroyed */;
7213 }
7214 }
7215}
7216SpecialCasedStyles.initialStylesByElement = new WeakMap();
7217if (false) {
7218 /** @type {?} */
7219 SpecialCasedStyles.initialStylesByElement;
7220 /**
7221 * @type {?}
7222 * @private
7223 */
7224 SpecialCasedStyles.prototype._state;
7225 /**
7226 * @type {?}
7227 * @private
7228 */
7229 SpecialCasedStyles.prototype._initialStyles;
7230 /**
7231 * @type {?}
7232 * @private
7233 */
7234 SpecialCasedStyles.prototype._element;
7235 /**
7236 * @type {?}
7237 * @private
7238 */
7239 SpecialCasedStyles.prototype._startStyles;
7240 /**
7241 * @type {?}
7242 * @private
7243 */
7244 SpecialCasedStyles.prototype._endStyles;
7245}
7246/** @enum {number} */
7247const SpecialCasedStylesState = {
7248 Pending: 0,
7249 Started: 1,
7250 Finished: 2,
7251 Destroyed: 3,
7252};
7253/**
7254 * @param {?} styles
7255 * @return {?}
7256 */
7257function filterNonAnimatableStyles(styles) {
7258 /** @type {?} */
7259 let result = null;
7260 /** @type {?} */
7261 const props = Object.keys(styles);
7262 for (let i = 0; i < props.length; i++) {
7263 /** @type {?} */
7264 const prop = props[i];
7265 if (isNonAnimatableStyle(prop)) {
7266 result = result || {};
7267 result[prop] = styles[prop];
7268 }
7269 }
7270 return result;
7271}
7272/**
7273 * @param {?} prop
7274 * @return {?}
7275 */
7276function isNonAnimatableStyle(prop) {
7277 return prop === 'display' || prop === 'position';
7278}
7279
7280/**
7281 * @fileoverview added by tsickle
7282 * Generated from: packages/animations/browser/src/render/css_keyframes/element_animation_style_handler.ts
7283 * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
7284 */
7285/**
7286 * @license
7287 * Copyright Google Inc. All Rights Reserved.
7288 *
7289 * Use of this source code is governed by an MIT-style license that can be
7290 * found in the LICENSE file at https://angular.io/license
7291 * @type {?}
7292 */
7293const ELAPSED_TIME_MAX_DECIMAL_PLACES = 3;
7294/** @type {?} */
7295const ANIMATION_PROP = 'animation';
7296/** @type {?} */
7297const ANIMATIONEND_EVENT = 'animationend';
7298/** @type {?} */
7299const ONE_SECOND$1 = 1000;
7300class ElementAnimationStyleHandler {
7301 /**
7302 * @param {?} _element
7303 * @param {?} _name
7304 * @param {?} _duration
7305 * @param {?} _delay
7306 * @param {?} _easing
7307 * @param {?} _fillMode
7308 * @param {?} _onDoneFn
7309 */
7310 constructor(_element, _name, _duration, _delay, _easing, _fillMode, _onDoneFn) {
7311 this._element = _element;
7312 this._name = _name;
7313 this._duration = _duration;
7314 this._delay = _delay;
7315 this._easing = _easing;
7316 this._fillMode = _fillMode;
7317 this._onDoneFn = _onDoneFn;
7318 this._finished = false;
7319 this._destroyed = false;
7320 this._startTime = 0;
7321 this._position = 0;
7322 this._eventFn = (/**
7323 * @param {?} e
7324 * @return {?}
7325 */
7326 (e) => this._handleCallback(e));
7327 }
7328 /**
7329 * @return {?}
7330 */
7331 apply() {
7332 applyKeyframeAnimation(this._element, `${this._duration}ms ${this._easing} ${this._delay}ms 1 normal ${this._fillMode} ${this._name}`);
7333 addRemoveAnimationEvent(this._element, this._eventFn, false);
7334 this._startTime = Date.now();
7335 }
7336 /**
7337 * @return {?}
7338 */
7339 pause() { playPauseAnimation(this._element, this._name, 'paused'); }
7340 /**
7341 * @return {?}
7342 */
7343 resume() { playPauseAnimation(this._element, this._name, 'running'); }
7344 /**
7345 * @param {?} position
7346 * @return {?}
7347 */
7348 setPosition(position) {
7349 /** @type {?} */
7350 const index = findIndexForAnimation(this._element, this._name);
7351 this._position = position * this._duration;
7352 setAnimationStyle(this._element, 'Delay', `-${this._position}ms`, index);
7353 }
7354 /**
7355 * @return {?}
7356 */
7357 getPosition() { return this._position; }
7358 /**
7359 * @private
7360 * @param {?} event
7361 * @return {?}
7362 */
7363 _handleCallback(event) {
7364 /** @type {?} */
7365 const timestamp = event._ngTestManualTimestamp || Date.now();
7366 /** @type {?} */
7367 const elapsedTime = parseFloat(event.elapsedTime.toFixed(ELAPSED_TIME_MAX_DECIMAL_PLACES)) * ONE_SECOND$1;
7368 if (event.animationName == this._name &&
7369 Math.max(timestamp - this._startTime, 0) >= this._delay && elapsedTime >= this._duration) {
7370 this.finish();
7371 }
7372 }
7373 /**
7374 * @return {?}
7375 */
7376 finish() {
7377 if (this._finished)
7378 return;
7379 this._finished = true;
7380 this._onDoneFn();
7381 addRemoveAnimationEvent(this._element, this._eventFn, true);
7382 }
7383 /**
7384 * @return {?}
7385 */
7386 destroy() {
7387 if (this._destroyed)
7388 return;
7389 this._destroyed = true;
7390 this.finish();
7391 removeKeyframeAnimation(this._element, this._name);
7392 }
7393}
7394if (false) {
7395 /**
7396 * @type {?}
7397 * @private
7398 */
7399 ElementAnimationStyleHandler.prototype._eventFn;
7400 /**
7401 * @type {?}
7402 * @private
7403 */
7404 ElementAnimationStyleHandler.prototype._finished;
7405 /**
7406 * @type {?}
7407 * @private
7408 */
7409 ElementAnimationStyleHandler.prototype._destroyed;
7410 /**
7411 * @type {?}
7412 * @private
7413 */
7414 ElementAnimationStyleHandler.prototype._startTime;
7415 /**
7416 * @type {?}
7417 * @private
7418 */
7419 ElementAnimationStyleHandler.prototype._position;
7420 /**
7421 * @type {?}
7422 * @private
7423 */
7424 ElementAnimationStyleHandler.prototype._element;
7425 /**
7426 * @type {?}
7427 * @private
7428 */
7429 ElementAnimationStyleHandler.prototype._name;
7430 /**
7431 * @type {?}
7432 * @private
7433 */
7434 ElementAnimationStyleHandler.prototype._duration;
7435 /**
7436 * @type {?}
7437 * @private
7438 */
7439 ElementAnimationStyleHandler.prototype._delay;
7440 /**
7441 * @type {?}
7442 * @private
7443 */
7444 ElementAnimationStyleHandler.prototype._easing;
7445 /**
7446 * @type {?}
7447 * @private
7448 */
7449 ElementAnimationStyleHandler.prototype._fillMode;
7450 /**
7451 * @type {?}
7452 * @private
7453 */
7454 ElementAnimationStyleHandler.prototype._onDoneFn;
7455}
7456/**
7457 * @param {?} element
7458 * @param {?} name
7459 * @param {?} status
7460 * @return {?}
7461 */
7462function playPauseAnimation(element, name, status) {
7463 /** @type {?} */
7464 const index = findIndexForAnimation(element, name);
7465 setAnimationStyle(element, 'PlayState', status, index);
7466}
7467/**
7468 * @param {?} element
7469 * @param {?} value
7470 * @return {?}
7471 */
7472function applyKeyframeAnimation(element, value) {
7473 /** @type {?} */
7474 const anim = getAnimationStyle(element, '').trim();
7475 /** @type {?} */
7476 let index = 0;
7477 if (anim.length) {
7478 index = countChars(anim, ',') + 1;
7479 value = `${anim}, ${value}`;
7480 }
7481 setAnimationStyle(element, '', value);
7482 return index;
7483}
7484/**
7485 * @param {?} element
7486 * @param {?} name
7487 * @return {?}
7488 */
7489function removeKeyframeAnimation(element, name) {
7490 /** @type {?} */
7491 const anim = getAnimationStyle(element, '');
7492 /** @type {?} */
7493 const tokens = anim.split(',');
7494 /** @type {?} */
7495 const index = findMatchingTokenIndex(tokens, name);
7496 if (index >= 0) {
7497 tokens.splice(index, 1);
7498 /** @type {?} */
7499 const newValue = tokens.join(',');
7500 setAnimationStyle(element, '', newValue);
7501 }
7502}
7503/**
7504 * @param {?} element
7505 * @param {?} value
7506 * @return {?}
7507 */
7508function findIndexForAnimation(element, value) {
7509 /** @type {?} */
7510 const anim = getAnimationStyle(element, '');
7511 if (anim.indexOf(',') > 0) {
7512 /** @type {?} */
7513 const tokens = anim.split(',');
7514 return findMatchingTokenIndex(tokens, value);
7515 }
7516 return findMatchingTokenIndex([anim], value);
7517}
7518/**
7519 * @param {?} tokens
7520 * @param {?} searchToken
7521 * @return {?}
7522 */
7523function findMatchingTokenIndex(tokens, searchToken) {
7524 for (let i = 0; i < tokens.length; i++) {
7525 if (tokens[i].indexOf(searchToken) >= 0) {
7526 return i;
7527 }
7528 }
7529 return -1;
7530}
7531/**
7532 * @param {?} element
7533 * @param {?} fn
7534 * @param {?} doRemove
7535 * @return {?}
7536 */
7537function addRemoveAnimationEvent(element, fn, doRemove) {
7538 doRemove ? element.removeEventListener(ANIMATIONEND_EVENT, fn) :
7539 element.addEventListener(ANIMATIONEND_EVENT, fn);
7540}
7541/**
7542 * @param {?} element
7543 * @param {?} name
7544 * @param {?} value
7545 * @param {?=} index
7546 * @return {?}
7547 */
7548function setAnimationStyle(element, name, value, index) {
7549 /** @type {?} */
7550 const prop = ANIMATION_PROP + name;
7551 if (index != null) {
7552 /** @type {?} */
7553 const oldValue = element.style[prop];
7554 if (oldValue.length) {
7555 /** @type {?} */
7556 const tokens = oldValue.split(',');
7557 tokens[index] = value;
7558 value = tokens.join(',');
7559 }
7560 }
7561 element.style[prop] = value;
7562}
7563/**
7564 * @param {?} element
7565 * @param {?} name
7566 * @return {?}
7567 */
7568function getAnimationStyle(element, name) {
7569 return element.style[ANIMATION_PROP + name];
7570}
7571/**
7572 * @param {?} value
7573 * @param {?} char
7574 * @return {?}
7575 */
7576function countChars(value, char) {
7577 /** @type {?} */
7578 let count = 0;
7579 for (let i = 0; i < value.length; i++) {
7580 /** @type {?} */
7581 const c = value.charAt(i);
7582 if (c === char)
7583 count++;
7584 }
7585 return count;
7586}
7587
7588/**
7589 * @fileoverview added by tsickle
7590 * Generated from: packages/animations/browser/src/render/css_keyframes/css_keyframes_player.ts
7591 * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
7592 */
7593/** @type {?} */
7594const DEFAULT_FILL_MODE = 'forwards';
7595/** @type {?} */
7596const DEFAULT_EASING = 'linear';
7597/** @enum {number} */
7598const AnimatorControlState = {
7599 INITIALIZED: 1, STARTED: 2, FINISHED: 3, DESTROYED: 4,
7600};
7601class CssKeyframesPlayer {
7602 /**
7603 * @param {?} element
7604 * @param {?} keyframes
7605 * @param {?} animationName
7606 * @param {?} _duration
7607 * @param {?} _delay
7608 * @param {?} easing
7609 * @param {?} _finalStyles
7610 * @param {?=} _specialStyles
7611 */
7612 constructor(element, keyframes, animationName, _duration, _delay, easing, _finalStyles, _specialStyles) {
7613 this.element = element;
7614 this.keyframes = keyframes;
7615 this.animationName = animationName;
7616 this._duration = _duration;
7617 this._delay = _delay;
7618 this._finalStyles = _finalStyles;
7619 this._specialStyles = _specialStyles;
7620 this._onDoneFns = [];
7621 this._onStartFns = [];
7622 this._onDestroyFns = [];
7623 this._started = false;
7624 this.currentSnapshot = {};
7625 this._state = 0;
7626 this.easing = easing || DEFAULT_EASING;
7627 this.totalTime = _duration + _delay;
7628 this._buildStyler();
7629 }
7630 /**
7631 * @param {?} fn
7632 * @return {?}
7633 */
7634 onStart(fn) { this._onStartFns.push(fn); }
7635 /**
7636 * @param {?} fn
7637 * @return {?}
7638 */
7639 onDone(fn) { this._onDoneFns.push(fn); }
7640 /**
7641 * @param {?} fn
7642 * @return {?}
7643 */
7644 onDestroy(fn) { this._onDestroyFns.push(fn); }
7645 /**
7646 * @return {?}
7647 */
7648 destroy() {
7649 this.init();
7650 if (this._state >= 4 /* DESTROYED */)
7651 return;
7652 this._state = 4 /* DESTROYED */;
7653 this._styler.destroy();
7654 this._flushStartFns();
7655 this._flushDoneFns();
7656 if (this._specialStyles) {
7657 this._specialStyles.destroy();
7658 }
7659 this._onDestroyFns.forEach((/**
7660 * @param {?} fn
7661 * @return {?}
7662 */
7663 fn => fn()));
7664 this._onDestroyFns = [];
7665 }
7666 /**
7667 * @private
7668 * @return {?}
7669 */
7670 _flushDoneFns() {
7671 this._onDoneFns.forEach((/**
7672 * @param {?} fn
7673 * @return {?}
7674 */
7675 fn => fn()));
7676 this._onDoneFns = [];
7677 }
7678 /**
7679 * @private
7680 * @return {?}
7681 */
7682 _flushStartFns() {
7683 this._onStartFns.forEach((/**
7684 * @param {?} fn
7685 * @return {?}
7686 */
7687 fn => fn()));
7688 this._onStartFns = [];
7689 }
7690 /**
7691 * @return {?}
7692 */
7693 finish() {
7694 this.init();
7695 if (this._state >= 3 /* FINISHED */)
7696 return;
7697 this._state = 3 /* FINISHED */;
7698 this._styler.finish();
7699 this._flushStartFns();
7700 if (this._specialStyles) {
7701 this._specialStyles.finish();
7702 }
7703 this._flushDoneFns();
7704 }
7705 /**
7706 * @param {?} value
7707 * @return {?}
7708 */
7709 setPosition(value) { this._styler.setPosition(value); }
7710 /**
7711 * @return {?}
7712 */
7713 getPosition() { return this._styler.getPosition(); }
7714 /**
7715 * @return {?}
7716 */
7717 hasStarted() { return this._state >= 2 /* STARTED */; }
7718 /**
7719 * @return {?}
7720 */
7721 init() {
7722 if (this._state >= 1 /* INITIALIZED */)
7723 return;
7724 this._state = 1 /* INITIALIZED */;
7725 /** @type {?} */
7726 const elm = this.element;
7727 this._styler.apply();
7728 if (this._delay) {
7729 this._styler.pause();
7730 }
7731 }
7732 /**
7733 * @return {?}
7734 */
7735 play() {
7736 this.init();
7737 if (!this.hasStarted()) {
7738 this._flushStartFns();
7739 this._state = 2 /* STARTED */;
7740 if (this._specialStyles) {
7741 this._specialStyles.start();
7742 }
7743 }
7744 this._styler.resume();
7745 }
7746 /**
7747 * @return {?}
7748 */
7749 pause() {
7750 this.init();
7751 this._styler.pause();
7752 }
7753 /**
7754 * @return {?}
7755 */
7756 restart() {
7757 this.reset();
7758 this.play();
7759 }
7760 /**
7761 * @return {?}
7762 */
7763 reset() {
7764 this._styler.destroy();
7765 this._buildStyler();
7766 this._styler.apply();
7767 }
7768 /**
7769 * @private
7770 * @return {?}
7771 */
7772 _buildStyler() {
7773 this._styler = new ElementAnimationStyleHandler(this.element, this.animationName, this._duration, this._delay, this.easing, DEFAULT_FILL_MODE, (/**
7774 * @return {?}
7775 */
7776 () => this.finish()));
7777 }
7778 /**
7779 * \@internal
7780 * @param {?} phaseName
7781 * @return {?}
7782 */
7783 triggerCallback(phaseName) {
7784 /** @type {?} */
7785 const methods = phaseName == 'start' ? this._onStartFns : this._onDoneFns;
7786 methods.forEach((/**
7787 * @param {?} fn
7788 * @return {?}
7789 */
7790 fn => fn()));
7791 methods.length = 0;
7792 }
7793 /**
7794 * @return {?}
7795 */
7796 beforeDestroy() {
7797 this.init();
7798 /** @type {?} */
7799 const styles = {};
7800 if (this.hasStarted()) {
7801 /** @type {?} */
7802 const finished = this._state >= 3 /* FINISHED */;
7803 Object.keys(this._finalStyles).forEach((/**
7804 * @param {?} prop
7805 * @return {?}
7806 */
7807 prop => {
7808 if (prop != 'offset') {
7809 styles[prop] = finished ? this._finalStyles[prop] : computeStyle(this.element, prop);
7810 }
7811 }));
7812 }
7813 this.currentSnapshot = styles;
7814 }
7815}
7816if (false) {
7817 /**
7818 * @type {?}
7819 * @private
7820 */
7821 CssKeyframesPlayer.prototype._onDoneFns;
7822 /**
7823 * @type {?}
7824 * @private
7825 */
7826 CssKeyframesPlayer.prototype._onStartFns;
7827 /**
7828 * @type {?}
7829 * @private
7830 */
7831 CssKeyframesPlayer.prototype._onDestroyFns;
7832 /**
7833 * @type {?}
7834 * @private
7835 */
7836 CssKeyframesPlayer.prototype._started;
7837 /**
7838 * @type {?}
7839 * @private
7840 */
7841 CssKeyframesPlayer.prototype._styler;
7842 /** @type {?} */
7843 CssKeyframesPlayer.prototype.parentPlayer;
7844 /** @type {?} */
7845 CssKeyframesPlayer.prototype.totalTime;
7846 /** @type {?} */
7847 CssKeyframesPlayer.prototype.easing;
7848 /** @type {?} */
7849 CssKeyframesPlayer.prototype.currentSnapshot;
7850 /**
7851 * @type {?}
7852 * @private
7853 */
7854 CssKeyframesPlayer.prototype._state;
7855 /** @type {?} */
7856 CssKeyframesPlayer.prototype.element;
7857 /** @type {?} */
7858 CssKeyframesPlayer.prototype.keyframes;
7859 /** @type {?} */
7860 CssKeyframesPlayer.prototype.animationName;
7861 /**
7862 * @type {?}
7863 * @private
7864 */
7865 CssKeyframesPlayer.prototype._duration;
7866 /**
7867 * @type {?}
7868 * @private
7869 */
7870 CssKeyframesPlayer.prototype._delay;
7871 /**
7872 * @type {?}
7873 * @private
7874 */
7875 CssKeyframesPlayer.prototype._finalStyles;
7876 /**
7877 * @type {?}
7878 * @private
7879 */
7880 CssKeyframesPlayer.prototype._specialStyles;
7881}
7882
7883/**
7884 * @fileoverview added by tsickle
7885 * Generated from: packages/animations/browser/src/render/css_keyframes/direct_style_player.ts
7886 * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
7887 */
7888class DirectStylePlayer extends NoopAnimationPlayer {
7889 /**
7890 * @param {?} element
7891 * @param {?} styles
7892 */
7893 constructor(element, styles) {
7894 super();
7895 this.element = element;
7896 this._startingStyles = {};
7897 this.__initialized = false;
7898 this._styles = hypenatePropsObject(styles);
7899 }
7900 /**
7901 * @return {?}
7902 */
7903 init() {
7904 if (this.__initialized || !this._startingStyles)
7905 return;
7906 this.__initialized = true;
7907 Object.keys(this._styles).forEach((/**
7908 * @param {?} prop
7909 * @return {?}
7910 */
7911 prop => {
7912 (/** @type {?} */ (this._startingStyles))[prop] = this.element.style[prop];
7913 }));
7914 super.init();
7915 }
7916 /**
7917 * @return {?}
7918 */
7919 play() {
7920 if (!this._startingStyles)
7921 return;
7922 this.init();
7923 Object.keys(this._styles)
7924 .forEach((/**
7925 * @param {?} prop
7926 * @return {?}
7927 */
7928 prop => this.element.style.setProperty(prop, this._styles[prop])));
7929 super.play();
7930 }
7931 /**
7932 * @return {?}
7933 */
7934 destroy() {
7935 if (!this._startingStyles)
7936 return;
7937 Object.keys(this._startingStyles).forEach((/**
7938 * @param {?} prop
7939 * @return {?}
7940 */
7941 prop => {
7942 /** @type {?} */
7943 const value = (/** @type {?} */ (this._startingStyles))[prop];
7944 if (value) {
7945 this.element.style.setProperty(prop, value);
7946 }
7947 else {
7948 this.element.style.removeProperty(prop);
7949 }
7950 }));
7951 this._startingStyles = null;
7952 super.destroy();
7953 }
7954}
7955if (false) {
7956 /**
7957 * @type {?}
7958 * @private
7959 */
7960 DirectStylePlayer.prototype._startingStyles;
7961 /**
7962 * @type {?}
7963 * @private
7964 */
7965 DirectStylePlayer.prototype.__initialized;
7966 /**
7967 * @type {?}
7968 * @private
7969 */
7970 DirectStylePlayer.prototype._styles;
7971 /** @type {?} */
7972 DirectStylePlayer.prototype.element;
7973}
7974
7975/**
7976 * @fileoverview added by tsickle
7977 * Generated from: packages/animations/browser/src/render/css_keyframes/css_keyframes_driver.ts
7978 * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
7979 */
7980/** @type {?} */
7981const KEYFRAMES_NAME_PREFIX = 'gen_css_kf_';
7982/** @type {?} */
7983const TAB_SPACE = ' ';
7984class CssKeyframesDriver {
7985 constructor() {
7986 this._count = 0;
7987 this._head = document.querySelector('head');
7988 this._warningIssued = false;
7989 }
7990 /**
7991 * @param {?} prop
7992 * @return {?}
7993 */
7994 validateStyleProperty(prop) { return validateStyleProperty(prop); }
7995 /**
7996 * @param {?} element
7997 * @param {?} selector
7998 * @return {?}
7999 */
8000 matchesElement(element, selector) {
8001 return matchesElement(element, selector);
8002 }
8003 /**
8004 * @param {?} elm1
8005 * @param {?} elm2
8006 * @return {?}
8007 */
8008 containsElement(elm1, elm2) { return containsElement(elm1, elm2); }
8009 /**
8010 * @param {?} element
8011 * @param {?} selector
8012 * @param {?} multi
8013 * @return {?}
8014 */
8015 query(element, selector, multi) {
8016 return invokeQuery(element, selector, multi);
8017 }
8018 /**
8019 * @param {?} element
8020 * @param {?} prop
8021 * @param {?=} defaultValue
8022 * @return {?}
8023 */
8024 computeStyle(element, prop, defaultValue) {
8025 return (/** @type {?} */ (((/** @type {?} */ (window.getComputedStyle(element))))[prop]));
8026 }
8027 /**
8028 * @param {?} element
8029 * @param {?} name
8030 * @param {?} keyframes
8031 * @return {?}
8032 */
8033 buildKeyframeElement(element, name, keyframes) {
8034 keyframes = keyframes.map((/**
8035 * @param {?} kf
8036 * @return {?}
8037 */
8038 kf => hypenatePropsObject(kf)));
8039 /** @type {?} */
8040 let keyframeStr = `@keyframes ${name} {\n`;
8041 /** @type {?} */
8042 let tab = '';
8043 keyframes.forEach((/**
8044 * @param {?} kf
8045 * @return {?}
8046 */
8047 kf => {
8048 tab = TAB_SPACE;
8049 /** @type {?} */
8050 const offset = parseFloat(kf['offset']);
8051 keyframeStr += `${tab}${offset * 100}% {\n`;
8052 tab += TAB_SPACE;
8053 Object.keys(kf).forEach((/**
8054 * @param {?} prop
8055 * @return {?}
8056 */
8057 prop => {
8058 /** @type {?} */
8059 const value = kf[prop];
8060 switch (prop) {
8061 case 'offset':
8062 return;
8063 case 'easing':
8064 if (value) {
8065 keyframeStr += `${tab}animation-timing-function: ${value};\n`;
8066 }
8067 return;
8068 default:
8069 keyframeStr += `${tab}${prop}: ${value};\n`;
8070 return;
8071 }
8072 }));
8073 keyframeStr += `${tab}}\n`;
8074 }));
8075 keyframeStr += `}\n`;
8076 /** @type {?} */
8077 const kfElm = document.createElement('style');
8078 kfElm.innerHTML = keyframeStr;
8079 return kfElm;
8080 }
8081 /**
8082 * @param {?} element
8083 * @param {?} keyframes
8084 * @param {?} duration
8085 * @param {?} delay
8086 * @param {?} easing
8087 * @param {?=} previousPlayers
8088 * @param {?=} scrubberAccessRequested
8089 * @return {?}
8090 */
8091 animate(element, keyframes, duration, delay, easing, previousPlayers = [], scrubberAccessRequested) {
8092 if (scrubberAccessRequested) {
8093 this._notifyFaultyScrubber();
8094 }
8095 /** @type {?} */
8096 const previousCssKeyframePlayers = (/** @type {?} */ (previousPlayers.filter((/**
8097 * @param {?} player
8098 * @return {?}
8099 */
8100 player => player instanceof CssKeyframesPlayer))));
8101 /** @type {?} */
8102 const previousStyles = {};
8103 if (allowPreviousPlayerStylesMerge(duration, delay)) {
8104 previousCssKeyframePlayers.forEach((/**
8105 * @param {?} player
8106 * @return {?}
8107 */
8108 player => {
8109 /** @type {?} */
8110 let styles = player.currentSnapshot;
8111 Object.keys(styles).forEach((/**
8112 * @param {?} prop
8113 * @return {?}
8114 */
8115 prop => previousStyles[prop] = styles[prop]));
8116 }));
8117 }
8118 keyframes = balancePreviousStylesIntoKeyframes(element, keyframes, previousStyles);
8119 /** @type {?} */
8120 const finalStyles = flattenKeyframesIntoStyles(keyframes);
8121 // if there is no animation then there is no point in applying
8122 // styles and waiting for an event to get fired. This causes lag.
8123 // It's better to just directly apply the styles to the element
8124 // via the direct styling animation player.
8125 if (duration == 0) {
8126 return new DirectStylePlayer(element, finalStyles);
8127 }
8128 /** @type {?} */
8129 const animationName = `${KEYFRAMES_NAME_PREFIX}${this._count++}`;
8130 /** @type {?} */
8131 const kfElm = this.buildKeyframeElement(element, animationName, keyframes);
8132 (/** @type {?} */ (document.querySelector('head'))).appendChild(kfElm);
8133 /** @type {?} */
8134 const specialStyles = packageNonAnimatableStyles(element, keyframes);
8135 /** @type {?} */
8136 const player = new CssKeyframesPlayer(element, keyframes, animationName, duration, delay, easing, finalStyles, specialStyles);
8137 player.onDestroy((/**
8138 * @return {?}
8139 */
8140 () => removeElement(kfElm)));
8141 return player;
8142 }
8143 /**
8144 * @private
8145 * @return {?}
8146 */
8147 _notifyFaultyScrubber() {
8148 if (!this._warningIssued) {
8149 console.warn('@angular/animations: please load the web-animations.js polyfill to allow programmatic access...\n', ' visit http://bit.ly/IWukam to learn more about using the web-animation-js polyfill.');
8150 this._warningIssued = true;
8151 }
8152 }
8153}
8154if (false) {
8155 /**
8156 * @type {?}
8157 * @private
8158 */
8159 CssKeyframesDriver.prototype._count;
8160 /**
8161 * @type {?}
8162 * @private
8163 */
8164 CssKeyframesDriver.prototype._head;
8165 /**
8166 * @type {?}
8167 * @private
8168 */
8169 CssKeyframesDriver.prototype._warningIssued;
8170}
8171/**
8172 * @param {?} keyframes
8173 * @return {?}
8174 */
8175function flattenKeyframesIntoStyles(keyframes) {
8176 /** @type {?} */
8177 let flatKeyframes = {};
8178 if (keyframes) {
8179 /** @type {?} */
8180 const kfs = Array.isArray(keyframes) ? keyframes : [keyframes];
8181 kfs.forEach((/**
8182 * @param {?} kf
8183 * @return {?}
8184 */
8185 kf => {
8186 Object.keys(kf).forEach((/**
8187 * @param {?} prop
8188 * @return {?}
8189 */
8190 prop => {
8191 if (prop == 'offset' || prop == 'easing')
8192 return;
8193 flatKeyframes[prop] = kf[prop];
8194 }));
8195 }));
8196 }
8197 return flatKeyframes;
8198}
8199/**
8200 * @param {?} node
8201 * @return {?}
8202 */
8203function removeElement(node) {
8204 node.parentNode.removeChild(node);
8205}
8206
8207/**
8208 * @fileoverview added by tsickle
8209 * Generated from: packages/animations/browser/src/render/web_animations/web_animations_player.ts
8210 * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
8211 */
8212class WebAnimationsPlayer {
8213 /**
8214 * @param {?} element
8215 * @param {?} keyframes
8216 * @param {?} options
8217 * @param {?=} _specialStyles
8218 */
8219 constructor(element, keyframes, options, _specialStyles) {
8220 this.element = element;
8221 this.keyframes = keyframes;
8222 this.options = options;
8223 this._specialStyles = _specialStyles;
8224 this._onDoneFns = [];
8225 this._onStartFns = [];
8226 this._onDestroyFns = [];
8227 this._initialized = false;
8228 this._finished = false;
8229 this._started = false;
8230 this._destroyed = false;
8231 this.time = 0;
8232 this.parentPlayer = null;
8233 this.currentSnapshot = {};
8234 this._duration = (/** @type {?} */ (options['duration']));
8235 this._delay = (/** @type {?} */ (options['delay'])) || 0;
8236 this.time = this._duration + this._delay;
8237 }
8238 /**
8239 * @private
8240 * @return {?}
8241 */
8242 _onFinish() {
8243 if (!this._finished) {
8244 this._finished = true;
8245 this._onDoneFns.forEach((/**
8246 * @param {?} fn
8247 * @return {?}
8248 */
8249 fn => fn()));
8250 this._onDoneFns = [];
8251 }
8252 }
8253 /**
8254 * @return {?}
8255 */
8256 init() {
8257 this._buildPlayer();
8258 this._preparePlayerBeforeStart();
8259 }
8260 /**
8261 * @private
8262 * @return {?}
8263 */
8264 _buildPlayer() {
8265 if (this._initialized)
8266 return;
8267 this._initialized = true;
8268 /** @type {?} */
8269 const keyframes = this.keyframes;
8270 ((/** @type {?} */ (this))).domPlayer =
8271 this._triggerWebAnimation(this.element, keyframes, this.options);
8272 this._finalKeyframe = keyframes.length ? keyframes[keyframes.length - 1] : {};
8273 this.domPlayer.addEventListener('finish', (/**
8274 * @return {?}
8275 */
8276 () => this._onFinish()));
8277 }
8278 /**
8279 * @private
8280 * @return {?}
8281 */
8282 _preparePlayerBeforeStart() {
8283 // this is required so that the player doesn't start to animate right away
8284 if (this._delay) {
8285 this._resetDomPlayerState();
8286 }
8287 else {
8288 this.domPlayer.pause();
8289 }
8290 }
8291 /**
8292 * \@internal
8293 * @param {?} element
8294 * @param {?} keyframes
8295 * @param {?} options
8296 * @return {?}
8297 */
8298 _triggerWebAnimation(element, keyframes, options) {
8299 // jscompiler doesn't seem to know animate is a native property because it's not fully
8300 // supported yet across common browsers (we polyfill it for Edge/Safari) [CL #143630929]
8301 return (/** @type {?} */ (element['animate'](keyframes, options)));
8302 }
8303 /**
8304 * @param {?} fn
8305 * @return {?}
8306 */
8307 onStart(fn) { this._onStartFns.push(fn); }
8308 /**
8309 * @param {?} fn
8310 * @return {?}
8311 */
8312 onDone(fn) { this._onDoneFns.push(fn); }
8313 /**
8314 * @param {?} fn
8315 * @return {?}
8316 */
8317 onDestroy(fn) { this._onDestroyFns.push(fn); }
8318 /**
8319 * @return {?}
8320 */
8321 play() {
8322 this._buildPlayer();
8323 if (!this.hasStarted()) {
8324 this._onStartFns.forEach((/**
8325 * @param {?} fn
8326 * @return {?}
8327 */
8328 fn => fn()));
8329 this._onStartFns = [];
8330 this._started = true;
8331 if (this._specialStyles) {
8332 this._specialStyles.start();
8333 }
8334 }
8335 this.domPlayer.play();
8336 }
8337 /**
8338 * @return {?}
8339 */
8340 pause() {
8341 this.init();
8342 this.domPlayer.pause();
8343 }
8344 /**
8345 * @return {?}
8346 */
8347 finish() {
8348 this.init();
8349 if (this._specialStyles) {
8350 this._specialStyles.finish();
8351 }
8352 this._onFinish();
8353 this.domPlayer.finish();
8354 }
8355 /**
8356 * @return {?}
8357 */
8358 reset() {
8359 this._resetDomPlayerState();
8360 this._destroyed = false;
8361 this._finished = false;
8362 this._started = false;
8363 }
8364 /**
8365 * @private
8366 * @return {?}
8367 */
8368 _resetDomPlayerState() {
8369 if (this.domPlayer) {
8370 this.domPlayer.cancel();
8371 }
8372 }
8373 /**
8374 * @return {?}
8375 */
8376 restart() {
8377 this.reset();
8378 this.play();
8379 }
8380 /**
8381 * @return {?}
8382 */
8383 hasStarted() { return this._started; }
8384 /**
8385 * @return {?}
8386 */
8387 destroy() {
8388 if (!this._destroyed) {
8389 this._destroyed = true;
8390 this._resetDomPlayerState();
8391 this._onFinish();
8392 if (this._specialStyles) {
8393 this._specialStyles.destroy();
8394 }
8395 this._onDestroyFns.forEach((/**
8396 * @param {?} fn
8397 * @return {?}
8398 */
8399 fn => fn()));
8400 this._onDestroyFns = [];
8401 }
8402 }
8403 /**
8404 * @param {?} p
8405 * @return {?}
8406 */
8407 setPosition(p) { this.domPlayer.currentTime = p * this.time; }
8408 /**
8409 * @return {?}
8410 */
8411 getPosition() { return this.domPlayer.currentTime / this.time; }
8412 /**
8413 * @return {?}
8414 */
8415 get totalTime() { return this._delay + this._duration; }
8416 /**
8417 * @return {?}
8418 */
8419 beforeDestroy() {
8420 /** @type {?} */
8421 const styles = {};
8422 if (this.hasStarted()) {
8423 Object.keys(this._finalKeyframe).forEach((/**
8424 * @param {?} prop
8425 * @return {?}
8426 */
8427 prop => {
8428 if (prop != 'offset') {
8429 styles[prop] =
8430 this._finished ? this._finalKeyframe[prop] : computeStyle(this.element, prop);
8431 }
8432 }));
8433 }
8434 this.currentSnapshot = styles;
8435 }
8436 /**
8437 * \@internal
8438 * @param {?} phaseName
8439 * @return {?}
8440 */
8441 triggerCallback(phaseName) {
8442 /** @type {?} */
8443 const methods = phaseName == 'start' ? this._onStartFns : this._onDoneFns;
8444 methods.forEach((/**
8445 * @param {?} fn
8446 * @return {?}
8447 */
8448 fn => fn()));
8449 methods.length = 0;
8450 }
8451}
8452if (false) {
8453 /**
8454 * @type {?}
8455 * @private
8456 */
8457 WebAnimationsPlayer.prototype._onDoneFns;
8458 /**
8459 * @type {?}
8460 * @private
8461 */
8462 WebAnimationsPlayer.prototype._onStartFns;
8463 /**
8464 * @type {?}
8465 * @private
8466 */
8467 WebAnimationsPlayer.prototype._onDestroyFns;
8468 /**
8469 * @type {?}
8470 * @private
8471 */
8472 WebAnimationsPlayer.prototype._duration;
8473 /**
8474 * @type {?}
8475 * @private
8476 */
8477 WebAnimationsPlayer.prototype._delay;
8478 /**
8479 * @type {?}
8480 * @private
8481 */
8482 WebAnimationsPlayer.prototype._initialized;
8483 /**
8484 * @type {?}
8485 * @private
8486 */
8487 WebAnimationsPlayer.prototype._finished;
8488 /**
8489 * @type {?}
8490 * @private
8491 */
8492 WebAnimationsPlayer.prototype._started;
8493 /**
8494 * @type {?}
8495 * @private
8496 */
8497 WebAnimationsPlayer.prototype._destroyed;
8498 /**
8499 * @type {?}
8500 * @private
8501 */
8502 WebAnimationsPlayer.prototype._finalKeyframe;
8503 /** @type {?} */
8504 WebAnimationsPlayer.prototype.domPlayer;
8505 /** @type {?} */
8506 WebAnimationsPlayer.prototype.time;
8507 /** @type {?} */
8508 WebAnimationsPlayer.prototype.parentPlayer;
8509 /** @type {?} */
8510 WebAnimationsPlayer.prototype.currentSnapshot;
8511 /** @type {?} */
8512 WebAnimationsPlayer.prototype.element;
8513 /** @type {?} */
8514 WebAnimationsPlayer.prototype.keyframes;
8515 /** @type {?} */
8516 WebAnimationsPlayer.prototype.options;
8517 /**
8518 * @type {?}
8519 * @private
8520 */
8521 WebAnimationsPlayer.prototype._specialStyles;
8522}
8523
8524/**
8525 * @fileoverview added by tsickle
8526 * Generated from: packages/animations/browser/src/render/web_animations/web_animations_driver.ts
8527 * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
8528 */
8529class WebAnimationsDriver {
8530 constructor() {
8531 this._isNativeImpl = /\{\s*\[native\s+code\]\s*\}/.test(getElementAnimateFn().toString());
8532 this._cssKeyframesDriver = new CssKeyframesDriver();
8533 }
8534 /**
8535 * @param {?} prop
8536 * @return {?}
8537 */
8538 validateStyleProperty(prop) { return validateStyleProperty(prop); }
8539 /**
8540 * @param {?} element
8541 * @param {?} selector
8542 * @return {?}
8543 */
8544 matchesElement(element, selector) {
8545 return matchesElement(element, selector);
8546 }
8547 /**
8548 * @param {?} elm1
8549 * @param {?} elm2
8550 * @return {?}
8551 */
8552 containsElement(elm1, elm2) { return containsElement(elm1, elm2); }
8553 /**
8554 * @param {?} element
8555 * @param {?} selector
8556 * @param {?} multi
8557 * @return {?}
8558 */
8559 query(element, selector, multi) {
8560 return invokeQuery(element, selector, multi);
8561 }
8562 /**
8563 * @param {?} element
8564 * @param {?} prop
8565 * @param {?=} defaultValue
8566 * @return {?}
8567 */
8568 computeStyle(element, prop, defaultValue) {
8569 return (/** @type {?} */ (((/** @type {?} */ (window.getComputedStyle(element))))[prop]));
8570 }
8571 /**
8572 * @param {?} supported
8573 * @return {?}
8574 */
8575 overrideWebAnimationsSupport(supported) { this._isNativeImpl = supported; }
8576 /**
8577 * @param {?} element
8578 * @param {?} keyframes
8579 * @param {?} duration
8580 * @param {?} delay
8581 * @param {?} easing
8582 * @param {?=} previousPlayers
8583 * @param {?=} scrubberAccessRequested
8584 * @return {?}
8585 */
8586 animate(element, keyframes, duration, delay, easing, previousPlayers = [], scrubberAccessRequested) {
8587 /** @type {?} */
8588 const useKeyframes = !scrubberAccessRequested && !this._isNativeImpl;
8589 if (useKeyframes) {
8590 return this._cssKeyframesDriver.animate(element, keyframes, duration, delay, easing, previousPlayers);
8591 }
8592 /** @type {?} */
8593 const fill = delay == 0 ? 'both' : 'forwards';
8594 /** @type {?} */
8595 const playerOptions = { duration, delay, fill };
8596 // we check for this to avoid having a null|undefined value be present
8597 // for the easing (which results in an error for certain browsers #9752)
8598 if (easing) {
8599 playerOptions['easing'] = easing;
8600 }
8601 /** @type {?} */
8602 const previousStyles = {};
8603 /** @type {?} */
8604 const previousWebAnimationPlayers = (/** @type {?} */ (previousPlayers.filter((/**
8605 * @param {?} player
8606 * @return {?}
8607 */
8608 player => player instanceof WebAnimationsPlayer))));
8609 if (allowPreviousPlayerStylesMerge(duration, delay)) {
8610 previousWebAnimationPlayers.forEach((/**
8611 * @param {?} player
8612 * @return {?}
8613 */
8614 player => {
8615 /** @type {?} */
8616 let styles = player.currentSnapshot;
8617 Object.keys(styles).forEach((/**
8618 * @param {?} prop
8619 * @return {?}
8620 */
8621 prop => previousStyles[prop] = styles[prop]));
8622 }));
8623 }
8624 keyframes = keyframes.map((/**
8625 * @param {?} styles
8626 * @return {?}
8627 */
8628 styles => copyStyles(styles, false)));
8629 keyframes = balancePreviousStylesIntoKeyframes(element, keyframes, previousStyles);
8630 /** @type {?} */
8631 const specialStyles = packageNonAnimatableStyles(element, keyframes);
8632 return new WebAnimationsPlayer(element, keyframes, playerOptions, specialStyles);
8633 }
8634}
8635if (false) {
8636 /**
8637 * @type {?}
8638 * @private
8639 */
8640 WebAnimationsDriver.prototype._isNativeImpl;
8641 /**
8642 * @type {?}
8643 * @private
8644 */
8645 WebAnimationsDriver.prototype._cssKeyframesDriver;
8646}
8647/**
8648 * @return {?}
8649 */
8650function supportsWebAnimations() {
8651 return typeof getElementAnimateFn() === 'function';
8652}
8653/**
8654 * @return {?}
8655 */
8656function getElementAnimateFn() {
8657 return (isBrowser() && ((/** @type {?} */ (Element))).prototype['animate']) || {};
8658}
8659
8660/**
8661 * @fileoverview added by tsickle
8662 * Generated from: packages/animations/browser/src/private_export.ts
8663 * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
8664 */
8665
8666/**
8667 * @fileoverview added by tsickle
8668 * Generated from: packages/animations/browser/src/browser.ts
8669 * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
8670 */
8671
8672/**
8673 * @fileoverview added by tsickle
8674 * Generated from: packages/animations/browser/public_api.ts
8675 * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
8676 */
8677
8678/**
8679 * @fileoverview added by tsickle
8680 * Generated from: packages/animations/browser/index.ts
8681 * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
8682 */
8683
8684/**
8685 * Generated bundle index. Do not edit.
8686 */
8687
8688export { AnimationDriver, Animation as ɵAnimation, AnimationDriver as ɵAnimationDriver, 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, SpecialCasedStyles as ɵangular_packages_animations_browser_browser_a, containsElement as ɵcontainsElement, invokeQuery as ɵinvokeQuery, matchesElement as ɵmatchesElement, supportsWebAnimations as ɵsupportsWebAnimations, validateStyleProperty as ɵvalidateStyleProperty };
8689//# sourceMappingURL=browser.js.map