UNPKG

234 kBJavaScriptView Raw
1/**
2 * @license Angular v8.2.11
3 * (c) 2010-2019 Google LLC. https://angular.io/
4 * License: MIT
5 */
6
7(function (global, factory) {
8 typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@angular/animations'), require('@angular/core')) :
9 typeof define === 'function' && define.amd ? define('@angular/animations/browser', ['exports', '@angular/animations', '@angular/core'], factory) :
10 (global = global || self, factory((global.ng = global.ng || {}, global.ng.animations = global.ng.animations || {}, global.ng.animations.browser = {}), global.ng.animations, global.ng.core));
11}(this, function (exports, animations, core) { 'use strict';
12
13 /*! *****************************************************************************
14 Copyright (c) Microsoft Corporation. All rights reserved.
15 Licensed under the Apache License, Version 2.0 (the "License"); you may not use
16 this file except in compliance with the License. You may obtain a copy of the
17 License at http://www.apache.org/licenses/LICENSE-2.0
18
19 THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
20 KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
21 WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
22 MERCHANTABLITY OR NON-INFRINGEMENT.
23
24 See the Apache Version 2.0 License for specific language governing permissions
25 and limitations under the License.
26 ***************************************************************************** */
27 /* global Reflect, Promise */
28
29 var extendStatics = function(d, b) {
30 extendStatics = Object.setPrototypeOf ||
31 ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
32 function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
33 return extendStatics(d, b);
34 };
35
36 function __extends(d, b) {
37 extendStatics(d, b);
38 function __() { this.constructor = d; }
39 d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
40 }
41
42 var __assign = function() {
43 __assign = Object.assign || function __assign(t) {
44 for (var s, i = 1, n = arguments.length; i < n; i++) {
45 s = arguments[i];
46 for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
47 }
48 return t;
49 };
50 return __assign.apply(this, arguments);
51 };
52
53 function __rest(s, e) {
54 var t = {};
55 for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
56 t[p] = s[p];
57 if (s != null && typeof Object.getOwnPropertySymbols === "function")
58 for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) if (e.indexOf(p[i]) < 0)
59 t[p[i]] = s[p[i]];
60 return t;
61 }
62
63 function __decorate(decorators, target, key, desc) {
64 var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
65 if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
66 else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
67 return c > 3 && r && Object.defineProperty(target, key, r), r;
68 }
69
70 function __param(paramIndex, decorator) {
71 return function (target, key) { decorator(target, key, paramIndex); }
72 }
73
74 function __metadata(metadataKey, metadataValue) {
75 if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(metadataKey, metadataValue);
76 }
77
78 function __awaiter(thisArg, _arguments, P, generator) {
79 return new (P || (P = Promise))(function (resolve, reject) {
80 function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
81 function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
82 function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
83 step((generator = generator.apply(thisArg, _arguments || [])).next());
84 });
85 }
86
87 function __generator(thisArg, body) {
88 var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
89 return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
90 function verb(n) { return function (v) { return step([n, v]); }; }
91 function step(op) {
92 if (f) throw new TypeError("Generator is already executing.");
93 while (_) try {
94 if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
95 if (y = 0, t) op = [op[0] & 2, t.value];
96 switch (op[0]) {
97 case 0: case 1: t = op; break;
98 case 4: _.label++; return { value: op[1], done: false };
99 case 5: _.label++; y = op[1]; op = [0]; continue;
100 case 7: op = _.ops.pop(); _.trys.pop(); continue;
101 default:
102 if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
103 if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
104 if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
105 if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
106 if (t[2]) _.ops.pop();
107 _.trys.pop(); continue;
108 }
109 op = body.call(thisArg, _);
110 } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
111 if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
112 }
113 }
114
115 function __exportStar(m, exports) {
116 for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];
117 }
118
119 function __values(o) {
120 var m = typeof Symbol === "function" && o[Symbol.iterator], i = 0;
121 if (m) return m.call(o);
122 return {
123 next: function () {
124 if (o && i >= o.length) o = void 0;
125 return { value: o && o[i++], done: !o };
126 }
127 };
128 }
129
130 function __read(o, n) {
131 var m = typeof Symbol === "function" && o[Symbol.iterator];
132 if (!m) return o;
133 var i = m.call(o), r, ar = [], e;
134 try {
135 while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
136 }
137 catch (error) { e = { error: error }; }
138 finally {
139 try {
140 if (r && !r.done && (m = i["return"])) m.call(i);
141 }
142 finally { if (e) throw e.error; }
143 }
144 return ar;
145 }
146
147 function __spread() {
148 for (var ar = [], i = 0; i < arguments.length; i++)
149 ar = ar.concat(__read(arguments[i]));
150 return ar;
151 }
152
153 function __await(v) {
154 return this instanceof __await ? (this.v = v, this) : new __await(v);
155 }
156
157 function __asyncGenerator(thisArg, _arguments, generator) {
158 if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
159 var g = generator.apply(thisArg, _arguments || []), i, q = [];
160 return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i;
161 function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; }
162 function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } }
163 function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); }
164 function fulfill(value) { resume("next", value); }
165 function reject(value) { resume("throw", value); }
166 function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); }
167 }
168
169 function __asyncDelegator(o) {
170 var i, p;
171 return i = {}, verb("next"), verb("throw", function (e) { throw e; }), verb("return"), i[Symbol.iterator] = function () { return this; }, i;
172 function verb(n, f) { i[n] = o[n] ? function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === "return" } : f ? f(v) : v; } : f; }
173 }
174
175 function __asyncValues(o) {
176 if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
177 var m = o[Symbol.asyncIterator], i;
178 return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i);
179 function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }
180 function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }
181 }
182
183 function __makeTemplateObject(cooked, raw) {
184 if (Object.defineProperty) { Object.defineProperty(cooked, "raw", { value: raw }); } else { cooked.raw = raw; }
185 return cooked;
186 };
187
188 function __importStar(mod) {
189 if (mod && mod.__esModule) return mod;
190 var result = {};
191 if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
192 result.default = mod;
193 return result;
194 }
195
196 function __importDefault(mod) {
197 return (mod && mod.__esModule) ? mod : { default: mod };
198 }
199
200 function isBrowser() {
201 return (typeof window !== 'undefined' && typeof window.document !== 'undefined');
202 }
203 function isNode() {
204 return (typeof process !== 'undefined');
205 }
206 function optimizeGroupPlayer(players) {
207 switch (players.length) {
208 case 0:
209 return new animations.NoopAnimationPlayer();
210 case 1:
211 return players[0];
212 default:
213 return new animations.ɵAnimationGroupPlayer(players);
214 }
215 }
216 function normalizeKeyframes(driver, normalizer, element, keyframes, preStyles, postStyles) {
217 if (preStyles === void 0) { preStyles = {}; }
218 if (postStyles === void 0) { postStyles = {}; }
219 var errors = [];
220 var normalizedKeyframes = [];
221 var previousOffset = -1;
222 var previousKeyframe = null;
223 keyframes.forEach(function (kf) {
224 var offset = kf['offset'];
225 var isSameOffset = offset == previousOffset;
226 var normalizedKeyframe = (isSameOffset && previousKeyframe) || {};
227 Object.keys(kf).forEach(function (prop) {
228 var normalizedProp = prop;
229 var normalizedValue = kf[prop];
230 if (prop !== 'offset') {
231 normalizedProp = normalizer.normalizePropertyName(normalizedProp, errors);
232 switch (normalizedValue) {
233 case animations.ɵPRE_STYLE:
234 normalizedValue = preStyles[prop];
235 break;
236 case animations.AUTO_STYLE:
237 normalizedValue = postStyles[prop];
238 break;
239 default:
240 normalizedValue =
241 normalizer.normalizeStyleValue(prop, normalizedProp, normalizedValue, errors);
242 break;
243 }
244 }
245 normalizedKeyframe[normalizedProp] = normalizedValue;
246 });
247 if (!isSameOffset) {
248 normalizedKeyframes.push(normalizedKeyframe);
249 }
250 previousKeyframe = normalizedKeyframe;
251 previousOffset = offset;
252 });
253 if (errors.length) {
254 var LINE_START = '\n - ';
255 throw new Error("Unable to animate due to the following errors:" + LINE_START + errors.join(LINE_START));
256 }
257 return normalizedKeyframes;
258 }
259 function listenOnPlayer(player, eventName, event, callback) {
260 switch (eventName) {
261 case 'start':
262 player.onStart(function () { return callback(event && copyAnimationEvent(event, 'start', player)); });
263 break;
264 case 'done':
265 player.onDone(function () { return callback(event && copyAnimationEvent(event, 'done', player)); });
266 break;
267 case 'destroy':
268 player.onDestroy(function () { return callback(event && copyAnimationEvent(event, 'destroy', player)); });
269 break;
270 }
271 }
272 function copyAnimationEvent(e, phaseName, player) {
273 var totalTime = player.totalTime;
274 var disabled = player.disabled ? true : false;
275 var event = makeAnimationEvent(e.element, e.triggerName, e.fromState, e.toState, phaseName || e.phaseName, totalTime == undefined ? e.totalTime : totalTime, disabled);
276 var data = e['_data'];
277 if (data != null) {
278 event['_data'] = data;
279 }
280 return event;
281 }
282 function makeAnimationEvent(element, triggerName, fromState, toState, phaseName, totalTime, disabled) {
283 if (phaseName === void 0) { phaseName = ''; }
284 if (totalTime === void 0) { totalTime = 0; }
285 return { element: element, triggerName: triggerName, fromState: fromState, toState: toState, phaseName: phaseName, totalTime: totalTime, disabled: !!disabled };
286 }
287 function getOrSetAsInMap(map, key, defaultValue) {
288 var value;
289 if (map instanceof Map) {
290 value = map.get(key);
291 if (!value) {
292 map.set(key, value = defaultValue);
293 }
294 }
295 else {
296 value = map[key];
297 if (!value) {
298 value = map[key] = defaultValue;
299 }
300 }
301 return value;
302 }
303 function parseTimelineCommand(command) {
304 var separatorPos = command.indexOf(':');
305 var id = command.substring(1, separatorPos);
306 var action = command.substr(separatorPos + 1);
307 return [id, action];
308 }
309 var _contains = function (elm1, elm2) { return false; };
310 var ɵ0 = _contains;
311 var _matches = function (element, selector) {
312 return false;
313 };
314 var ɵ1 = _matches;
315 var _query = function (element, selector, multi) {
316 return [];
317 };
318 var ɵ2 = _query;
319 // Define utility methods for browsers and platform-server(domino) where Element
320 // and utility methods exist.
321 var _isNode = isNode();
322 if (_isNode || typeof Element !== 'undefined') {
323 // this is well supported in all browsers
324 _contains = function (elm1, elm2) { return elm1.contains(elm2); };
325 _matches = (function () {
326 if (_isNode || Element.prototype.matches) {
327 return function (element, selector) { return element.matches(selector); };
328 }
329 else {
330 var proto = Element.prototype;
331 var fn_1 = proto.matchesSelector || proto.mozMatchesSelector || proto.msMatchesSelector ||
332 proto.oMatchesSelector || proto.webkitMatchesSelector;
333 if (fn_1) {
334 return function (element, selector) { return fn_1.apply(element, [selector]); };
335 }
336 else {
337 return _matches;
338 }
339 }
340 })();
341 _query = function (element, selector, multi) {
342 var results = [];
343 if (multi) {
344 results.push.apply(results, __spread(element.querySelectorAll(selector)));
345 }
346 else {
347 var elm = element.querySelector(selector);
348 if (elm) {
349 results.push(elm);
350 }
351 }
352 return results;
353 };
354 }
355 function containsVendorPrefix(prop) {
356 // Webkit is the only real popular vendor prefix nowadays
357 // cc: http://shouldiprefix.com/
358 return prop.substring(1, 6) == 'ebkit'; // webkit or Webkit
359 }
360 var _CACHED_BODY = null;
361 var _IS_WEBKIT = false;
362 function validateStyleProperty(prop) {
363 if (!_CACHED_BODY) {
364 _CACHED_BODY = getBodyNode() || {};
365 _IS_WEBKIT = _CACHED_BODY.style ? ('WebkitAppearance' in _CACHED_BODY.style) : false;
366 }
367 var result = true;
368 if (_CACHED_BODY.style && !containsVendorPrefix(prop)) {
369 result = prop in _CACHED_BODY.style;
370 if (!result && _IS_WEBKIT) {
371 var camelProp = 'Webkit' + prop.charAt(0).toUpperCase() + prop.substr(1);
372 result = camelProp in _CACHED_BODY.style;
373 }
374 }
375 return result;
376 }
377 function getBodyNode() {
378 if (typeof document != 'undefined') {
379 return document.body;
380 }
381 return null;
382 }
383 var matchesElement = _matches;
384 var containsElement = _contains;
385 var invokeQuery = _query;
386 function hypenatePropsObject(object) {
387 var newObj = {};
388 Object.keys(object).forEach(function (prop) {
389 var newProp = prop.replace(/([a-z])([A-Z])/g, '$1-$2');
390 newObj[newProp] = object[prop];
391 });
392 return newObj;
393 }
394
395 /**
396 * @publicApi
397 */
398 var NoopAnimationDriver = /** @class */ (function () {
399 function NoopAnimationDriver() {
400 }
401 NoopAnimationDriver.prototype.validateStyleProperty = function (prop) { return validateStyleProperty(prop); };
402 NoopAnimationDriver.prototype.matchesElement = function (element, selector) {
403 return matchesElement(element, selector);
404 };
405 NoopAnimationDriver.prototype.containsElement = function (elm1, elm2) { return containsElement(elm1, elm2); };
406 NoopAnimationDriver.prototype.query = function (element, selector, multi) {
407 return invokeQuery(element, selector, multi);
408 };
409 NoopAnimationDriver.prototype.computeStyle = function (element, prop, defaultValue) {
410 return defaultValue || '';
411 };
412 NoopAnimationDriver.prototype.animate = function (element, keyframes, duration, delay, easing, previousPlayers, scrubberAccessRequested) {
413 if (previousPlayers === void 0) { previousPlayers = []; }
414 return new animations.NoopAnimationPlayer(duration, delay);
415 };
416 NoopAnimationDriver = __decorate([
417 core.Injectable()
418 ], NoopAnimationDriver);
419 return NoopAnimationDriver;
420 }());
421 /**
422 * @publicApi
423 */
424 var AnimationDriver = /** @class */ (function () {
425 function AnimationDriver() {
426 }
427 AnimationDriver.NOOP = new NoopAnimationDriver();
428 return AnimationDriver;
429 }());
430
431 /**
432 * @license
433 * Copyright Google Inc. All Rights Reserved.
434 *
435 * Use of this source code is governed by an MIT-style license that can be
436 * found in the LICENSE file at https://angular.io/license
437 */
438 var ONE_SECOND = 1000;
439 var SUBSTITUTION_EXPR_START = '{{';
440 var SUBSTITUTION_EXPR_END = '}}';
441 var ENTER_CLASSNAME = 'ng-enter';
442 var LEAVE_CLASSNAME = 'ng-leave';
443 var ENTER_SELECTOR = '.ng-enter';
444 var LEAVE_SELECTOR = '.ng-leave';
445 var NG_TRIGGER_CLASSNAME = 'ng-trigger';
446 var NG_TRIGGER_SELECTOR = '.ng-trigger';
447 var NG_ANIMATING_CLASSNAME = 'ng-animating';
448 var NG_ANIMATING_SELECTOR = '.ng-animating';
449 function resolveTimingValue(value) {
450 if (typeof value == 'number')
451 return value;
452 var matches = value.match(/^(-?[\.\d]+)(m?s)/);
453 if (!matches || matches.length < 2)
454 return 0;
455 return _convertTimeValueToMS(parseFloat(matches[1]), matches[2]);
456 }
457 function _convertTimeValueToMS(value, unit) {
458 switch (unit) {
459 case 's':
460 return value * ONE_SECOND;
461 default: // ms or something else
462 return value;
463 }
464 }
465 function resolveTiming(timings, errors, allowNegativeValues) {
466 return timings.hasOwnProperty('duration') ?
467 timings :
468 parseTimeExpression(timings, errors, allowNegativeValues);
469 }
470 function parseTimeExpression(exp, errors, allowNegativeValues) {
471 var regex = /^(-?[\.\d]+)(m?s)(?:\s+(-?[\.\d]+)(m?s))?(?:\s+([-a-z]+(?:\(.+?\))?))?$/i;
472 var duration;
473 var delay = 0;
474 var easing = '';
475 if (typeof exp === 'string') {
476 var matches = exp.match(regex);
477 if (matches === null) {
478 errors.push("The provided timing value \"" + exp + "\" is invalid.");
479 return { duration: 0, delay: 0, easing: '' };
480 }
481 duration = _convertTimeValueToMS(parseFloat(matches[1]), matches[2]);
482 var delayMatch = matches[3];
483 if (delayMatch != null) {
484 delay = _convertTimeValueToMS(parseFloat(delayMatch), matches[4]);
485 }
486 var easingVal = matches[5];
487 if (easingVal) {
488 easing = easingVal;
489 }
490 }
491 else {
492 duration = exp;
493 }
494 if (!allowNegativeValues) {
495 var containsErrors = false;
496 var startIndex = errors.length;
497 if (duration < 0) {
498 errors.push("Duration values below 0 are not allowed for this animation step.");
499 containsErrors = true;
500 }
501 if (delay < 0) {
502 errors.push("Delay values below 0 are not allowed for this animation step.");
503 containsErrors = true;
504 }
505 if (containsErrors) {
506 errors.splice(startIndex, 0, "The provided timing value \"" + exp + "\" is invalid.");
507 }
508 }
509 return { duration: duration, delay: delay, easing: easing };
510 }
511 function copyObj(obj, destination) {
512 if (destination === void 0) { destination = {}; }
513 Object.keys(obj).forEach(function (prop) { destination[prop] = obj[prop]; });
514 return destination;
515 }
516 function normalizeStyles(styles) {
517 var normalizedStyles = {};
518 if (Array.isArray(styles)) {
519 styles.forEach(function (data) { return copyStyles(data, false, normalizedStyles); });
520 }
521 else {
522 copyStyles(styles, false, normalizedStyles);
523 }
524 return normalizedStyles;
525 }
526 function copyStyles(styles, readPrototype, destination) {
527 if (destination === void 0) { destination = {}; }
528 if (readPrototype) {
529 // we make use of a for-in loop so that the
530 // prototypically inherited properties are
531 // revealed from the backFill map
532 for (var prop in styles) {
533 destination[prop] = styles[prop];
534 }
535 }
536 else {
537 copyObj(styles, destination);
538 }
539 return destination;
540 }
541 function getStyleAttributeString(element, key, value) {
542 // Return the key-value pair string to be added to the style attribute for the
543 // given CSS style key.
544 if (value) {
545 return key + ':' + value + ';';
546 }
547 else {
548 return '';
549 }
550 }
551 function writeStyleAttribute(element) {
552 // Read the style property of the element and manually reflect it to the
553 // style attribute. This is needed because Domino on platform-server doesn't
554 // understand the full set of allowed CSS properties and doesn't reflect some
555 // of them automatically.
556 var styleAttrValue = '';
557 for (var i = 0; i < element.style.length; i++) {
558 var key = element.style.item(i);
559 styleAttrValue += getStyleAttributeString(element, key, element.style.getPropertyValue(key));
560 }
561 for (var key in element.style) {
562 // Skip internal Domino properties that don't need to be reflected.
563 if (!element.style.hasOwnProperty(key) || key.startsWith('_')) {
564 continue;
565 }
566 var dashKey = camelCaseToDashCase(key);
567 styleAttrValue += getStyleAttributeString(element, dashKey, element.style[key]);
568 }
569 element.setAttribute('style', styleAttrValue);
570 }
571 function setStyles(element, styles, formerStyles) {
572 if (element['style']) {
573 Object.keys(styles).forEach(function (prop) {
574 var camelProp = dashCaseToCamelCase(prop);
575 if (formerStyles && !formerStyles.hasOwnProperty(prop)) {
576 formerStyles[prop] = element.style[camelProp];
577 }
578 element.style[camelProp] = styles[prop];
579 });
580 // On the server set the 'style' attribute since it's not automatically reflected.
581 if (isNode()) {
582 writeStyleAttribute(element);
583 }
584 }
585 }
586 function eraseStyles(element, styles) {
587 if (element['style']) {
588 Object.keys(styles).forEach(function (prop) {
589 var camelProp = dashCaseToCamelCase(prop);
590 element.style[camelProp] = '';
591 });
592 // On the server set the 'style' attribute since it's not automatically reflected.
593 if (isNode()) {
594 writeStyleAttribute(element);
595 }
596 }
597 }
598 function normalizeAnimationEntry(steps) {
599 if (Array.isArray(steps)) {
600 if (steps.length == 1)
601 return steps[0];
602 return animations.sequence(steps);
603 }
604 return steps;
605 }
606 function validateStyleParams(value, options, errors) {
607 var params = options.params || {};
608 var matches = extractStyleParams(value);
609 if (matches.length) {
610 matches.forEach(function (varName) {
611 if (!params.hasOwnProperty(varName)) {
612 errors.push("Unable to resolve the local animation param " + varName + " in the given list of values");
613 }
614 });
615 }
616 }
617 var PARAM_REGEX = new RegExp(SUBSTITUTION_EXPR_START + "\\s*(.+?)\\s*" + SUBSTITUTION_EXPR_END, 'g');
618 function extractStyleParams(value) {
619 var params = [];
620 if (typeof value === 'string') {
621 var val = value.toString();
622 var match = void 0;
623 while (match = PARAM_REGEX.exec(val)) {
624 params.push(match[1]);
625 }
626 PARAM_REGEX.lastIndex = 0;
627 }
628 return params;
629 }
630 function interpolateParams(value, params, errors) {
631 var original = value.toString();
632 var str = original.replace(PARAM_REGEX, function (_, varName) {
633 var localVal = params[varName];
634 // this means that the value was never overridden by the data passed in by the user
635 if (!params.hasOwnProperty(varName)) {
636 errors.push("Please provide a value for the animation param " + varName);
637 localVal = '';
638 }
639 return localVal.toString();
640 });
641 // we do this to assert that numeric values stay as they are
642 return str == original ? value : str;
643 }
644 function iteratorToArray(iterator) {
645 var arr = [];
646 var item = iterator.next();
647 while (!item.done) {
648 arr.push(item.value);
649 item = iterator.next();
650 }
651 return arr;
652 }
653 function mergeAnimationOptions(source, destination) {
654 if (source.params) {
655 var p0_1 = source.params;
656 if (!destination.params) {
657 destination.params = {};
658 }
659 var p1_1 = destination.params;
660 Object.keys(p0_1).forEach(function (param) {
661 if (!p1_1.hasOwnProperty(param)) {
662 p1_1[param] = p0_1[param];
663 }
664 });
665 }
666 return destination;
667 }
668 var DASH_CASE_REGEXP = /-+([a-z0-9])/g;
669 function dashCaseToCamelCase(input) {
670 return input.replace(DASH_CASE_REGEXP, function () {
671 var m = [];
672 for (var _i = 0; _i < arguments.length; _i++) {
673 m[_i] = arguments[_i];
674 }
675 return m[1].toUpperCase();
676 });
677 }
678 function camelCaseToDashCase(input) {
679 return input.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase();
680 }
681 function allowPreviousPlayerStylesMerge(duration, delay) {
682 return duration === 0 || delay === 0;
683 }
684 function balancePreviousStylesIntoKeyframes(element, keyframes, previousStyles) {
685 var previousStyleProps = Object.keys(previousStyles);
686 if (previousStyleProps.length && keyframes.length) {
687 var startingKeyframe_1 = keyframes[0];
688 var missingStyleProps_1 = [];
689 previousStyleProps.forEach(function (prop) {
690 if (!startingKeyframe_1.hasOwnProperty(prop)) {
691 missingStyleProps_1.push(prop);
692 }
693 startingKeyframe_1[prop] = previousStyles[prop];
694 });
695 if (missingStyleProps_1.length) {
696 var _loop_1 = function () {
697 var kf = keyframes[i];
698 missingStyleProps_1.forEach(function (prop) { kf[prop] = computeStyle(element, prop); });
699 };
700 // tslint:disable-next-line
701 for (var i = 1; i < keyframes.length; i++) {
702 _loop_1();
703 }
704 }
705 }
706 return keyframes;
707 }
708 function visitDslNode(visitor, node, context) {
709 switch (node.type) {
710 case 7 /* Trigger */:
711 return visitor.visitTrigger(node, context);
712 case 0 /* State */:
713 return visitor.visitState(node, context);
714 case 1 /* Transition */:
715 return visitor.visitTransition(node, context);
716 case 2 /* Sequence */:
717 return visitor.visitSequence(node, context);
718 case 3 /* Group */:
719 return visitor.visitGroup(node, context);
720 case 4 /* Animate */:
721 return visitor.visitAnimate(node, context);
722 case 5 /* Keyframes */:
723 return visitor.visitKeyframes(node, context);
724 case 6 /* Style */:
725 return visitor.visitStyle(node, context);
726 case 8 /* Reference */:
727 return visitor.visitReference(node, context);
728 case 9 /* AnimateChild */:
729 return visitor.visitAnimateChild(node, context);
730 case 10 /* AnimateRef */:
731 return visitor.visitAnimateRef(node, context);
732 case 11 /* Query */:
733 return visitor.visitQuery(node, context);
734 case 12 /* Stagger */:
735 return visitor.visitStagger(node, context);
736 default:
737 throw new Error("Unable to resolve animation metadata node #" + node.type);
738 }
739 }
740 function computeStyle(element, prop) {
741 return window.getComputedStyle(element)[prop];
742 }
743
744 /**
745 * @license
746 * Copyright Google Inc. All Rights Reserved.
747 *
748 * Use of this source code is governed by an MIT-style license that can be
749 * found in the LICENSE file at https://angular.io/license
750 */
751 var ANY_STATE = '*';
752 function parseTransitionExpr(transitionValue, errors) {
753 var expressions = [];
754 if (typeof transitionValue == 'string') {
755 transitionValue
756 .split(/\s*,\s*/)
757 .forEach(function (str) { return parseInnerTransitionStr(str, expressions, errors); });
758 }
759 else {
760 expressions.push(transitionValue);
761 }
762 return expressions;
763 }
764 function parseInnerTransitionStr(eventStr, expressions, errors) {
765 if (eventStr[0] == ':') {
766 var result = parseAnimationAlias(eventStr, errors);
767 if (typeof result == 'function') {
768 expressions.push(result);
769 return;
770 }
771 eventStr = result;
772 }
773 var match = eventStr.match(/^(\*|[-\w]+)\s*(<?[=-]>)\s*(\*|[-\w]+)$/);
774 if (match == null || match.length < 4) {
775 errors.push("The provided transition expression \"" + eventStr + "\" is not supported");
776 return expressions;
777 }
778 var fromState = match[1];
779 var separator = match[2];
780 var toState = match[3];
781 expressions.push(makeLambdaFromStates(fromState, toState));
782 var isFullAnyStateExpr = fromState == ANY_STATE && toState == ANY_STATE;
783 if (separator[0] == '<' && !isFullAnyStateExpr) {
784 expressions.push(makeLambdaFromStates(toState, fromState));
785 }
786 }
787 function parseAnimationAlias(alias, errors) {
788 switch (alias) {
789 case ':enter':
790 return 'void => *';
791 case ':leave':
792 return '* => void';
793 case ':increment':
794 return function (fromState, toState) { return parseFloat(toState) > parseFloat(fromState); };
795 case ':decrement':
796 return function (fromState, toState) { return parseFloat(toState) < parseFloat(fromState); };
797 default:
798 errors.push("The transition alias value \"" + alias + "\" is not supported");
799 return '* => *';
800 }
801 }
802 // DO NOT REFACTOR ... keep the follow set instantiations
803 // with the values intact (closure compiler for some reason
804 // removes follow-up lines that add the values outside of
805 // the constructor...
806 var TRUE_BOOLEAN_VALUES = new Set(['true', '1']);
807 var FALSE_BOOLEAN_VALUES = new Set(['false', '0']);
808 function makeLambdaFromStates(lhs, rhs) {
809 var LHS_MATCH_BOOLEAN = TRUE_BOOLEAN_VALUES.has(lhs) || FALSE_BOOLEAN_VALUES.has(lhs);
810 var RHS_MATCH_BOOLEAN = TRUE_BOOLEAN_VALUES.has(rhs) || FALSE_BOOLEAN_VALUES.has(rhs);
811 return function (fromState, toState) {
812 var lhsMatch = lhs == ANY_STATE || lhs == fromState;
813 var rhsMatch = rhs == ANY_STATE || rhs == toState;
814 if (!lhsMatch && LHS_MATCH_BOOLEAN && typeof fromState === 'boolean') {
815 lhsMatch = fromState ? TRUE_BOOLEAN_VALUES.has(lhs) : FALSE_BOOLEAN_VALUES.has(lhs);
816 }
817 if (!rhsMatch && RHS_MATCH_BOOLEAN && typeof toState === 'boolean') {
818 rhsMatch = toState ? TRUE_BOOLEAN_VALUES.has(rhs) : FALSE_BOOLEAN_VALUES.has(rhs);
819 }
820 return lhsMatch && rhsMatch;
821 };
822 }
823
824 var SELF_TOKEN = ':self';
825 var SELF_TOKEN_REGEX = new RegExp("s*" + SELF_TOKEN + "s*,?", 'g');
826 /*
827 * [Validation]
828 * The visitor code below will traverse the animation AST generated by the animation verb functions
829 * (the output is a tree of objects) and attempt to perform a series of validations on the data. The
830 * following corner-cases will be validated:
831 *
832 * 1. Overlap of animations
833 * Given that a CSS property cannot be animated in more than one place at the same time, it's
834 * important that this behavior is detected and validated. The way in which this occurs is that
835 * each time a style property is examined, a string-map containing the property will be updated with
836 * the start and end times for when the property is used within an animation step.
837 *
838 * If there are two or more parallel animations that are currently running (these are invoked by the
839 * group()) on the same element then the validator will throw an error. Since the start/end timing
840 * values are collected for each property then if the current animation step is animating the same
841 * property and its timing values fall anywhere into the window of time that the property is
842 * currently being animated within then this is what causes an error.
843 *
844 * 2. Timing values
845 * The validator will validate to see if a timing value of `duration delay easing` or
846 * `durationNumber` is valid or not.
847 *
848 * (note that upon validation the code below will replace the timing data with an object containing
849 * {duration,delay,easing}.
850 *
851 * 3. Offset Validation
852 * Each of the style() calls are allowed to have an offset value when placed inside of keyframes().
853 * Offsets within keyframes() are considered valid when:
854 *
855 * - No offsets are used at all
856 * - Each style() entry contains an offset value
857 * - Each offset is between 0 and 1
858 * - Each offset is greater to or equal than the previous one
859 *
860 * Otherwise an error will be thrown.
861 */
862 function buildAnimationAst(driver, metadata, errors) {
863 return new AnimationAstBuilderVisitor(driver).build(metadata, errors);
864 }
865 var ROOT_SELECTOR = '';
866 var AnimationAstBuilderVisitor = /** @class */ (function () {
867 function AnimationAstBuilderVisitor(_driver) {
868 this._driver = _driver;
869 }
870 AnimationAstBuilderVisitor.prototype.build = function (metadata, errors) {
871 var context = new AnimationAstBuilderContext(errors);
872 this._resetContextStyleTimingState(context);
873 return visitDslNode(this, normalizeAnimationEntry(metadata), context);
874 };
875 AnimationAstBuilderVisitor.prototype._resetContextStyleTimingState = function (context) {
876 context.currentQuerySelector = ROOT_SELECTOR;
877 context.collectedStyles = {};
878 context.collectedStyles[ROOT_SELECTOR] = {};
879 context.currentTime = 0;
880 };
881 AnimationAstBuilderVisitor.prototype.visitTrigger = function (metadata, context) {
882 var _this = this;
883 var queryCount = context.queryCount = 0;
884 var depCount = context.depCount = 0;
885 var states = [];
886 var transitions = [];
887 if (metadata.name.charAt(0) == '@') {
888 context.errors.push('animation triggers cannot be prefixed with an `@` sign (e.g. trigger(\'@foo\', [...]))');
889 }
890 metadata.definitions.forEach(function (def) {
891 _this._resetContextStyleTimingState(context);
892 if (def.type == 0 /* State */) {
893 var stateDef_1 = def;
894 var name_1 = stateDef_1.name;
895 name_1.toString().split(/\s*,\s*/).forEach(function (n) {
896 stateDef_1.name = n;
897 states.push(_this.visitState(stateDef_1, context));
898 });
899 stateDef_1.name = name_1;
900 }
901 else if (def.type == 1 /* Transition */) {
902 var transition = _this.visitTransition(def, context);
903 queryCount += transition.queryCount;
904 depCount += transition.depCount;
905 transitions.push(transition);
906 }
907 else {
908 context.errors.push('only state() and transition() definitions can sit inside of a trigger()');
909 }
910 });
911 return {
912 type: 7 /* Trigger */,
913 name: metadata.name, states: states, transitions: transitions, queryCount: queryCount, depCount: depCount,
914 options: null
915 };
916 };
917 AnimationAstBuilderVisitor.prototype.visitState = function (metadata, context) {
918 var styleAst = this.visitStyle(metadata.styles, context);
919 var astParams = (metadata.options && metadata.options.params) || null;
920 if (styleAst.containsDynamicStyles) {
921 var missingSubs_1 = new Set();
922 var params_1 = astParams || {};
923 styleAst.styles.forEach(function (value) {
924 if (isObject(value)) {
925 var stylesObj_1 = value;
926 Object.keys(stylesObj_1).forEach(function (prop) {
927 extractStyleParams(stylesObj_1[prop]).forEach(function (sub) {
928 if (!params_1.hasOwnProperty(sub)) {
929 missingSubs_1.add(sub);
930 }
931 });
932 });
933 }
934 });
935 if (missingSubs_1.size) {
936 var missingSubsArr = iteratorToArray(missingSubs_1.values());
937 context.errors.push("state(\"" + metadata.name + "\", ...) must define default values for all the following style substitutions: " + missingSubsArr.join(', '));
938 }
939 }
940 return {
941 type: 0 /* State */,
942 name: metadata.name,
943 style: styleAst,
944 options: astParams ? { params: astParams } : null
945 };
946 };
947 AnimationAstBuilderVisitor.prototype.visitTransition = function (metadata, context) {
948 context.queryCount = 0;
949 context.depCount = 0;
950 var animation = visitDslNode(this, normalizeAnimationEntry(metadata.animation), context);
951 var matchers = parseTransitionExpr(metadata.expr, context.errors);
952 return {
953 type: 1 /* Transition */,
954 matchers: matchers,
955 animation: animation,
956 queryCount: context.queryCount,
957 depCount: context.depCount,
958 options: normalizeAnimationOptions(metadata.options)
959 };
960 };
961 AnimationAstBuilderVisitor.prototype.visitSequence = function (metadata, context) {
962 var _this = this;
963 return {
964 type: 2 /* Sequence */,
965 steps: metadata.steps.map(function (s) { return visitDslNode(_this, s, context); }),
966 options: normalizeAnimationOptions(metadata.options)
967 };
968 };
969 AnimationAstBuilderVisitor.prototype.visitGroup = function (metadata, context) {
970 var _this = this;
971 var currentTime = context.currentTime;
972 var furthestTime = 0;
973 var steps = metadata.steps.map(function (step) {
974 context.currentTime = currentTime;
975 var innerAst = visitDslNode(_this, step, context);
976 furthestTime = Math.max(furthestTime, context.currentTime);
977 return innerAst;
978 });
979 context.currentTime = furthestTime;
980 return {
981 type: 3 /* Group */,
982 steps: steps,
983 options: normalizeAnimationOptions(metadata.options)
984 };
985 };
986 AnimationAstBuilderVisitor.prototype.visitAnimate = function (metadata, context) {
987 var timingAst = constructTimingAst(metadata.timings, context.errors);
988 context.currentAnimateTimings = timingAst;
989 var styleAst;
990 var styleMetadata = metadata.styles ? metadata.styles : animations.style({});
991 if (styleMetadata.type == 5 /* Keyframes */) {
992 styleAst = this.visitKeyframes(styleMetadata, context);
993 }
994 else {
995 var styleMetadata_1 = metadata.styles;
996 var isEmpty = false;
997 if (!styleMetadata_1) {
998 isEmpty = true;
999 var newStyleData = {};
1000 if (timingAst.easing) {
1001 newStyleData['easing'] = timingAst.easing;
1002 }
1003 styleMetadata_1 = animations.style(newStyleData);
1004 }
1005 context.currentTime += timingAst.duration + timingAst.delay;
1006 var _styleAst = this.visitStyle(styleMetadata_1, context);
1007 _styleAst.isEmptyStep = isEmpty;
1008 styleAst = _styleAst;
1009 }
1010 context.currentAnimateTimings = null;
1011 return {
1012 type: 4 /* Animate */,
1013 timings: timingAst,
1014 style: styleAst,
1015 options: null
1016 };
1017 };
1018 AnimationAstBuilderVisitor.prototype.visitStyle = function (metadata, context) {
1019 var ast = this._makeStyleAst(metadata, context);
1020 this._validateStyleAst(ast, context);
1021 return ast;
1022 };
1023 AnimationAstBuilderVisitor.prototype._makeStyleAst = function (metadata, context) {
1024 var styles = [];
1025 if (Array.isArray(metadata.styles)) {
1026 metadata.styles.forEach(function (styleTuple) {
1027 if (typeof styleTuple == 'string') {
1028 if (styleTuple == animations.AUTO_STYLE) {
1029 styles.push(styleTuple);
1030 }
1031 else {
1032 context.errors.push("The provided style string value " + styleTuple + " is not allowed.");
1033 }
1034 }
1035 else {
1036 styles.push(styleTuple);
1037 }
1038 });
1039 }
1040 else {
1041 styles.push(metadata.styles);
1042 }
1043 var containsDynamicStyles = false;
1044 var collectedEasing = null;
1045 styles.forEach(function (styleData) {
1046 if (isObject(styleData)) {
1047 var styleMap = styleData;
1048 var easing = styleMap['easing'];
1049 if (easing) {
1050 collectedEasing = easing;
1051 delete styleMap['easing'];
1052 }
1053 if (!containsDynamicStyles) {
1054 for (var prop in styleMap) {
1055 var value = styleMap[prop];
1056 if (value.toString().indexOf(SUBSTITUTION_EXPR_START) >= 0) {
1057 containsDynamicStyles = true;
1058 break;
1059 }
1060 }
1061 }
1062 }
1063 });
1064 return {
1065 type: 6 /* Style */,
1066 styles: styles,
1067 easing: collectedEasing,
1068 offset: metadata.offset, containsDynamicStyles: containsDynamicStyles,
1069 options: null
1070 };
1071 };
1072 AnimationAstBuilderVisitor.prototype._validateStyleAst = function (ast, context) {
1073 var _this = this;
1074 var timings = context.currentAnimateTimings;
1075 var endTime = context.currentTime;
1076 var startTime = context.currentTime;
1077 if (timings && startTime > 0) {
1078 startTime -= timings.duration + timings.delay;
1079 }
1080 ast.styles.forEach(function (tuple) {
1081 if (typeof tuple == 'string')
1082 return;
1083 Object.keys(tuple).forEach(function (prop) {
1084 if (!_this._driver.validateStyleProperty(prop)) {
1085 context.errors.push("The provided animation property \"" + prop + "\" is not a supported CSS property for animations");
1086 return;
1087 }
1088 var collectedStyles = context.collectedStyles[context.currentQuerySelector];
1089 var collectedEntry = collectedStyles[prop];
1090 var updateCollectedStyle = true;
1091 if (collectedEntry) {
1092 if (startTime != endTime && startTime >= collectedEntry.startTime &&
1093 endTime <= collectedEntry.endTime) {
1094 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\"");
1095 updateCollectedStyle = false;
1096 }
1097 // we always choose the smaller start time value since we
1098 // want to have a record of the entire animation window where
1099 // the style property is being animated in between
1100 startTime = collectedEntry.startTime;
1101 }
1102 if (updateCollectedStyle) {
1103 collectedStyles[prop] = { startTime: startTime, endTime: endTime };
1104 }
1105 if (context.options) {
1106 validateStyleParams(tuple[prop], context.options, context.errors);
1107 }
1108 });
1109 });
1110 };
1111 AnimationAstBuilderVisitor.prototype.visitKeyframes = function (metadata, context) {
1112 var _this = this;
1113 var ast = { type: 5 /* Keyframes */, styles: [], options: null };
1114 if (!context.currentAnimateTimings) {
1115 context.errors.push("keyframes() must be placed inside of a call to animate()");
1116 return ast;
1117 }
1118 var MAX_KEYFRAME_OFFSET = 1;
1119 var totalKeyframesWithOffsets = 0;
1120 var offsets = [];
1121 var offsetsOutOfOrder = false;
1122 var keyframesOutOfRange = false;
1123 var previousOffset = 0;
1124 var keyframes = metadata.steps.map(function (styles) {
1125 var style = _this._makeStyleAst(styles, context);
1126 var offsetVal = style.offset != null ? style.offset : consumeOffset(style.styles);
1127 var offset = 0;
1128 if (offsetVal != null) {
1129 totalKeyframesWithOffsets++;
1130 offset = style.offset = offsetVal;
1131 }
1132 keyframesOutOfRange = keyframesOutOfRange || offset < 0 || offset > 1;
1133 offsetsOutOfOrder = offsetsOutOfOrder || offset < previousOffset;
1134 previousOffset = offset;
1135 offsets.push(offset);
1136 return style;
1137 });
1138 if (keyframesOutOfRange) {
1139 context.errors.push("Please ensure that all keyframe offsets are between 0 and 1");
1140 }
1141 if (offsetsOutOfOrder) {
1142 context.errors.push("Please ensure that all keyframe offsets are in order");
1143 }
1144 var length = metadata.steps.length;
1145 var generatedOffset = 0;
1146 if (totalKeyframesWithOffsets > 0 && totalKeyframesWithOffsets < length) {
1147 context.errors.push("Not all style() steps within the declared keyframes() contain offsets");
1148 }
1149 else if (totalKeyframesWithOffsets == 0) {
1150 generatedOffset = MAX_KEYFRAME_OFFSET / (length - 1);
1151 }
1152 var limit = length - 1;
1153 var currentTime = context.currentTime;
1154 var currentAnimateTimings = context.currentAnimateTimings;
1155 var animateDuration = currentAnimateTimings.duration;
1156 keyframes.forEach(function (kf, i) {
1157 var offset = generatedOffset > 0 ? (i == limit ? 1 : (generatedOffset * i)) : offsets[i];
1158 var durationUpToThisFrame = offset * animateDuration;
1159 context.currentTime = currentTime + currentAnimateTimings.delay + durationUpToThisFrame;
1160 currentAnimateTimings.duration = durationUpToThisFrame;
1161 _this._validateStyleAst(kf, context);
1162 kf.offset = offset;
1163 ast.styles.push(kf);
1164 });
1165 return ast;
1166 };
1167 AnimationAstBuilderVisitor.prototype.visitReference = function (metadata, context) {
1168 return {
1169 type: 8 /* Reference */,
1170 animation: visitDslNode(this, normalizeAnimationEntry(metadata.animation), context),
1171 options: normalizeAnimationOptions(metadata.options)
1172 };
1173 };
1174 AnimationAstBuilderVisitor.prototype.visitAnimateChild = function (metadata, context) {
1175 context.depCount++;
1176 return {
1177 type: 9 /* AnimateChild */,
1178 options: normalizeAnimationOptions(metadata.options)
1179 };
1180 };
1181 AnimationAstBuilderVisitor.prototype.visitAnimateRef = function (metadata, context) {
1182 return {
1183 type: 10 /* AnimateRef */,
1184 animation: this.visitReference(metadata.animation, context),
1185 options: normalizeAnimationOptions(metadata.options)
1186 };
1187 };
1188 AnimationAstBuilderVisitor.prototype.visitQuery = function (metadata, context) {
1189 var parentSelector = context.currentQuerySelector;
1190 var options = (metadata.options || {});
1191 context.queryCount++;
1192 context.currentQuery = metadata;
1193 var _a = __read(normalizeSelector(metadata.selector), 2), selector = _a[0], includeSelf = _a[1];
1194 context.currentQuerySelector =
1195 parentSelector.length ? (parentSelector + ' ' + selector) : selector;
1196 getOrSetAsInMap(context.collectedStyles, context.currentQuerySelector, {});
1197 var animation = visitDslNode(this, normalizeAnimationEntry(metadata.animation), context);
1198 context.currentQuery = null;
1199 context.currentQuerySelector = parentSelector;
1200 return {
1201 type: 11 /* Query */,
1202 selector: selector,
1203 limit: options.limit || 0,
1204 optional: !!options.optional, includeSelf: includeSelf, animation: animation,
1205 originalSelector: metadata.selector,
1206 options: normalizeAnimationOptions(metadata.options)
1207 };
1208 };
1209 AnimationAstBuilderVisitor.prototype.visitStagger = function (metadata, context) {
1210 if (!context.currentQuery) {
1211 context.errors.push("stagger() can only be used inside of query()");
1212 }
1213 var timings = metadata.timings === 'full' ?
1214 { duration: 0, delay: 0, easing: 'full' } :
1215 resolveTiming(metadata.timings, context.errors, true);
1216 return {
1217 type: 12 /* Stagger */,
1218 animation: visitDslNode(this, normalizeAnimationEntry(metadata.animation), context), timings: timings,
1219 options: null
1220 };
1221 };
1222 return AnimationAstBuilderVisitor;
1223 }());
1224 function normalizeSelector(selector) {
1225 var hasAmpersand = selector.split(/\s*,\s*/).find(function (token) { return token == SELF_TOKEN; }) ? true : false;
1226 if (hasAmpersand) {
1227 selector = selector.replace(SELF_TOKEN_REGEX, '');
1228 }
1229 // the :enter and :leave selectors are filled in at runtime during timeline building
1230 selector = selector.replace(/@\*/g, NG_TRIGGER_SELECTOR)
1231 .replace(/@\w+/g, function (match) { return NG_TRIGGER_SELECTOR + '-' + match.substr(1); })
1232 .replace(/:animating/g, NG_ANIMATING_SELECTOR);
1233 return [selector, hasAmpersand];
1234 }
1235 function normalizeParams(obj) {
1236 return obj ? copyObj(obj) : null;
1237 }
1238 var AnimationAstBuilderContext = /** @class */ (function () {
1239 function AnimationAstBuilderContext(errors) {
1240 this.errors = errors;
1241 this.queryCount = 0;
1242 this.depCount = 0;
1243 this.currentTransition = null;
1244 this.currentQuery = null;
1245 this.currentQuerySelector = null;
1246 this.currentAnimateTimings = null;
1247 this.currentTime = 0;
1248 this.collectedStyles = {};
1249 this.options = null;
1250 }
1251 return AnimationAstBuilderContext;
1252 }());
1253 function consumeOffset(styles) {
1254 if (typeof styles == 'string')
1255 return null;
1256 var offset = null;
1257 if (Array.isArray(styles)) {
1258 styles.forEach(function (styleTuple) {
1259 if (isObject(styleTuple) && styleTuple.hasOwnProperty('offset')) {
1260 var obj = styleTuple;
1261 offset = parseFloat(obj['offset']);
1262 delete obj['offset'];
1263 }
1264 });
1265 }
1266 else if (isObject(styles) && styles.hasOwnProperty('offset')) {
1267 var obj = styles;
1268 offset = parseFloat(obj['offset']);
1269 delete obj['offset'];
1270 }
1271 return offset;
1272 }
1273 function isObject(value) {
1274 return !Array.isArray(value) && typeof value == 'object';
1275 }
1276 function constructTimingAst(value, errors) {
1277 var timings = null;
1278 if (value.hasOwnProperty('duration')) {
1279 timings = value;
1280 }
1281 else if (typeof value == 'number') {
1282 var duration = resolveTiming(value, errors).duration;
1283 return makeTimingAst(duration, 0, '');
1284 }
1285 var strValue = value;
1286 var isDynamic = strValue.split(/\s+/).some(function (v) { return v.charAt(0) == '{' && v.charAt(1) == '{'; });
1287 if (isDynamic) {
1288 var ast = makeTimingAst(0, 0, '');
1289 ast.dynamic = true;
1290 ast.strValue = strValue;
1291 return ast;
1292 }
1293 timings = timings || resolveTiming(strValue, errors);
1294 return makeTimingAst(timings.duration, timings.delay, timings.easing);
1295 }
1296 function normalizeAnimationOptions(options) {
1297 if (options) {
1298 options = copyObj(options);
1299 if (options['params']) {
1300 options['params'] = normalizeParams(options['params']);
1301 }
1302 }
1303 else {
1304 options = {};
1305 }
1306 return options;
1307 }
1308 function makeTimingAst(duration, delay, easing) {
1309 return { duration: duration, delay: delay, easing: easing };
1310 }
1311
1312 function createTimelineInstruction(element, keyframes, preStyleProps, postStyleProps, duration, delay, easing, subTimeline) {
1313 if (easing === void 0) { easing = null; }
1314 if (subTimeline === void 0) { subTimeline = false; }
1315 return {
1316 type: 1 /* TimelineAnimation */,
1317 element: element,
1318 keyframes: keyframes,
1319 preStyleProps: preStyleProps,
1320 postStyleProps: postStyleProps,
1321 duration: duration,
1322 delay: delay,
1323 totalTime: duration + delay, easing: easing, subTimeline: subTimeline
1324 };
1325 }
1326
1327 var ElementInstructionMap = /** @class */ (function () {
1328 function ElementInstructionMap() {
1329 this._map = new Map();
1330 }
1331 ElementInstructionMap.prototype.consume = function (element) {
1332 var instructions = this._map.get(element);
1333 if (instructions) {
1334 this._map.delete(element);
1335 }
1336 else {
1337 instructions = [];
1338 }
1339 return instructions;
1340 };
1341 ElementInstructionMap.prototype.append = function (element, instructions) {
1342 var existingInstructions = this._map.get(element);
1343 if (!existingInstructions) {
1344 this._map.set(element, existingInstructions = []);
1345 }
1346 existingInstructions.push.apply(existingInstructions, __spread(instructions));
1347 };
1348 ElementInstructionMap.prototype.has = function (element) { return this._map.has(element); };
1349 ElementInstructionMap.prototype.clear = function () { this._map.clear(); };
1350 return ElementInstructionMap;
1351 }());
1352
1353 var ONE_FRAME_IN_MILLISECONDS = 1;
1354 var ENTER_TOKEN = ':enter';
1355 var ENTER_TOKEN_REGEX = new RegExp(ENTER_TOKEN, 'g');
1356 var LEAVE_TOKEN = ':leave';
1357 var LEAVE_TOKEN_REGEX = new RegExp(LEAVE_TOKEN, 'g');
1358 /*
1359 * The code within this file aims to generate web-animations-compatible keyframes from Angular's
1360 * animation DSL code.
1361 *
1362 * The code below will be converted from:
1363 *
1364 * ```
1365 * sequence([
1366 * style({ opacity: 0 }),
1367 * animate(1000, style({ opacity: 0 }))
1368 * ])
1369 * ```
1370 *
1371 * To:
1372 * ```
1373 * keyframes = [{ opacity: 0, offset: 0 }, { opacity: 1, offset: 1 }]
1374 * duration = 1000
1375 * delay = 0
1376 * easing = ''
1377 * ```
1378 *
1379 * For this operation to cover the combination of animation verbs (style, animate, group, etc...) a
1380 * combination of prototypical inheritance, AST traversal and merge-sort-like algorithms are used.
1381 *
1382 * [AST Traversal]
1383 * Each of the animation verbs, when executed, will return an string-map object representing what
1384 * type of action it is (style, animate, group, etc...) and the data associated with it. This means
1385 * that when functional composition mix of these functions is evaluated (like in the example above)
1386 * then it will end up producing a tree of objects representing the animation itself.
1387 *
1388 * When this animation object tree is processed by the visitor code below it will visit each of the
1389 * verb statements within the visitor. And during each visit it will build the context of the
1390 * animation keyframes by interacting with the `TimelineBuilder`.
1391 *
1392 * [TimelineBuilder]
1393 * This class is responsible for tracking the styles and building a series of keyframe objects for a
1394 * timeline between a start and end time. The builder starts off with an initial timeline and each
1395 * time the AST comes across a `group()`, `keyframes()` or a combination of the two wihtin a
1396 * `sequence()` then it will generate a sub timeline for each step as well as a new one after
1397 * they are complete.
1398 *
1399 * As the AST is traversed, the timing state on each of the timelines will be incremented. If a sub
1400 * timeline was created (based on one of the cases above) then the parent timeline will attempt to
1401 * merge the styles used within the sub timelines into itself (only with group() this will happen).
1402 * This happens with a merge operation (much like how the merge works in mergesort) and it will only
1403 * copy the most recently used styles from the sub timelines into the parent timeline. This ensures
1404 * that if the styles are used later on in another phase of the animation then they will be the most
1405 * up-to-date values.
1406 *
1407 * [How Missing Styles Are Updated]
1408 * Each timeline has a `backFill` property which is responsible for filling in new styles into
1409 * already processed keyframes if a new style shows up later within the animation sequence.
1410 *
1411 * ```
1412 * sequence([
1413 * style({ width: 0 }),
1414 * animate(1000, style({ width: 100 })),
1415 * animate(1000, style({ width: 200 })),
1416 * animate(1000, style({ width: 300 }))
1417 * animate(1000, style({ width: 400, height: 400 })) // notice how `height` doesn't exist anywhere
1418 * else
1419 * ])
1420 * ```
1421 *
1422 * What is happening here is that the `height` value is added later in the sequence, but is missing
1423 * from all previous animation steps. Therefore when a keyframe is created it would also be missing
1424 * from all previous keyframes up until where it is first used. For the timeline keyframe generation
1425 * to properly fill in the style it will place the previous value (the value from the parent
1426 * timeline) or a default value of `*` into the backFill object. Given that each of the keyframe
1427 * styles are objects that prototypically inhert from the backFill object, this means that if a
1428 * value is added into the backFill then it will automatically propagate any missing values to all
1429 * keyframes. Therefore the missing `height` value will be properly filled into the already
1430 * processed keyframes.
1431 *
1432 * When a sub-timeline is created it will have its own backFill property. This is done so that
1433 * styles present within the sub-timeline do not accidentally seep into the previous/future timeline
1434 * keyframes
1435 *
1436 * (For prototypically-inherited contents to be detected a `for(i in obj)` loop must be used.)
1437 *
1438 * [Validation]
1439 * The code in this file is not responsible for validation. That functionality happens with within
1440 * the `AnimationValidatorVisitor` code.
1441 */
1442 function buildAnimationTimelines(driver, rootElement, ast, enterClassName, leaveClassName, startingStyles, finalStyles, options, subInstructions, errors) {
1443 if (startingStyles === void 0) { startingStyles = {}; }
1444 if (finalStyles === void 0) { finalStyles = {}; }
1445 if (errors === void 0) { errors = []; }
1446 return new AnimationTimelineBuilderVisitor().buildKeyframes(driver, rootElement, ast, enterClassName, leaveClassName, startingStyles, finalStyles, options, subInstructions, errors);
1447 }
1448 var AnimationTimelineBuilderVisitor = /** @class */ (function () {
1449 function AnimationTimelineBuilderVisitor() {
1450 }
1451 AnimationTimelineBuilderVisitor.prototype.buildKeyframes = function (driver, rootElement, ast, enterClassName, leaveClassName, startingStyles, finalStyles, options, subInstructions, errors) {
1452 if (errors === void 0) { errors = []; }
1453 subInstructions = subInstructions || new ElementInstructionMap();
1454 var context = new AnimationTimelineContext(driver, rootElement, subInstructions, enterClassName, leaveClassName, errors, []);
1455 context.options = options;
1456 context.currentTimeline.setStyles([startingStyles], null, context.errors, options);
1457 visitDslNode(this, ast, context);
1458 // this checks to see if an actual animation happened
1459 var timelines = context.timelines.filter(function (timeline) { return timeline.containsAnimation(); });
1460 if (timelines.length && Object.keys(finalStyles).length) {
1461 var tl = timelines[timelines.length - 1];
1462 if (!tl.allowOnlyTimelineStyles()) {
1463 tl.setStyles([finalStyles], null, context.errors, options);
1464 }
1465 }
1466 return timelines.length ? timelines.map(function (timeline) { return timeline.buildKeyframes(); }) :
1467 [createTimelineInstruction(rootElement, [], [], [], 0, 0, '', false)];
1468 };
1469 AnimationTimelineBuilderVisitor.prototype.visitTrigger = function (ast, context) {
1470 // these values are not visited in this AST
1471 };
1472 AnimationTimelineBuilderVisitor.prototype.visitState = function (ast, context) {
1473 // these values are not visited in this AST
1474 };
1475 AnimationTimelineBuilderVisitor.prototype.visitTransition = function (ast, context) {
1476 // these values are not visited in this AST
1477 };
1478 AnimationTimelineBuilderVisitor.prototype.visitAnimateChild = function (ast, context) {
1479 var elementInstructions = context.subInstructions.consume(context.element);
1480 if (elementInstructions) {
1481 var innerContext = context.createSubContext(ast.options);
1482 var startTime = context.currentTimeline.currentTime;
1483 var endTime = this._visitSubInstructions(elementInstructions, innerContext, innerContext.options);
1484 if (startTime != endTime) {
1485 // we do this on the upper context because we created a sub context for
1486 // the sub child animations
1487 context.transformIntoNewTimeline(endTime);
1488 }
1489 }
1490 context.previousNode = ast;
1491 };
1492 AnimationTimelineBuilderVisitor.prototype.visitAnimateRef = function (ast, context) {
1493 var innerContext = context.createSubContext(ast.options);
1494 innerContext.transformIntoNewTimeline();
1495 this.visitReference(ast.animation, innerContext);
1496 context.transformIntoNewTimeline(innerContext.currentTimeline.currentTime);
1497 context.previousNode = ast;
1498 };
1499 AnimationTimelineBuilderVisitor.prototype._visitSubInstructions = function (instructions, context, options) {
1500 var startTime = context.currentTimeline.currentTime;
1501 var furthestTime = startTime;
1502 // this is a special-case for when a user wants to skip a sub
1503 // animation from being fired entirely.
1504 var duration = options.duration != null ? resolveTimingValue(options.duration) : null;
1505 var delay = options.delay != null ? resolveTimingValue(options.delay) : null;
1506 if (duration !== 0) {
1507 instructions.forEach(function (instruction) {
1508 var instructionTimings = context.appendInstructionToTimeline(instruction, duration, delay);
1509 furthestTime =
1510 Math.max(furthestTime, instructionTimings.duration + instructionTimings.delay);
1511 });
1512 }
1513 return furthestTime;
1514 };
1515 AnimationTimelineBuilderVisitor.prototype.visitReference = function (ast, context) {
1516 context.updateOptions(ast.options, true);
1517 visitDslNode(this, ast.animation, context);
1518 context.previousNode = ast;
1519 };
1520 AnimationTimelineBuilderVisitor.prototype.visitSequence = function (ast, context) {
1521 var _this = this;
1522 var subContextCount = context.subContextCount;
1523 var ctx = context;
1524 var options = ast.options;
1525 if (options && (options.params || options.delay)) {
1526 ctx = context.createSubContext(options);
1527 ctx.transformIntoNewTimeline();
1528 if (options.delay != null) {
1529 if (ctx.previousNode.type == 6 /* Style */) {
1530 ctx.currentTimeline.snapshotCurrentStyles();
1531 ctx.previousNode = DEFAULT_NOOP_PREVIOUS_NODE;
1532 }
1533 var delay = resolveTimingValue(options.delay);
1534 ctx.delayNextStep(delay);
1535 }
1536 }
1537 if (ast.steps.length) {
1538 ast.steps.forEach(function (s) { return visitDslNode(_this, s, ctx); });
1539 // this is here just incase the inner steps only contain or end with a style() call
1540 ctx.currentTimeline.applyStylesToKeyframe();
1541 // this means that some animation function within the sequence
1542 // ended up creating a sub timeline (which means the current
1543 // timeline cannot overlap with the contents of the sequence)
1544 if (ctx.subContextCount > subContextCount) {
1545 ctx.transformIntoNewTimeline();
1546 }
1547 }
1548 context.previousNode = ast;
1549 };
1550 AnimationTimelineBuilderVisitor.prototype.visitGroup = function (ast, context) {
1551 var _this = this;
1552 var innerTimelines = [];
1553 var furthestTime = context.currentTimeline.currentTime;
1554 var delay = ast.options && ast.options.delay ? resolveTimingValue(ast.options.delay) : 0;
1555 ast.steps.forEach(function (s) {
1556 var innerContext = context.createSubContext(ast.options);
1557 if (delay) {
1558 innerContext.delayNextStep(delay);
1559 }
1560 visitDslNode(_this, s, innerContext);
1561 furthestTime = Math.max(furthestTime, innerContext.currentTimeline.currentTime);
1562 innerTimelines.push(innerContext.currentTimeline);
1563 });
1564 // this operation is run after the AST loop because otherwise
1565 // if the parent timeline's collected styles were updated then
1566 // it would pass in invalid data into the new-to-be forked items
1567 innerTimelines.forEach(function (timeline) { return context.currentTimeline.mergeTimelineCollectedStyles(timeline); });
1568 context.transformIntoNewTimeline(furthestTime);
1569 context.previousNode = ast;
1570 };
1571 AnimationTimelineBuilderVisitor.prototype._visitTiming = function (ast, context) {
1572 if (ast.dynamic) {
1573 var strValue = ast.strValue;
1574 var timingValue = context.params ? interpolateParams(strValue, context.params, context.errors) : strValue;
1575 return resolveTiming(timingValue, context.errors);
1576 }
1577 else {
1578 return { duration: ast.duration, delay: ast.delay, easing: ast.easing };
1579 }
1580 };
1581 AnimationTimelineBuilderVisitor.prototype.visitAnimate = function (ast, context) {
1582 var timings = context.currentAnimateTimings = this._visitTiming(ast.timings, context);
1583 var timeline = context.currentTimeline;
1584 if (timings.delay) {
1585 context.incrementTime(timings.delay);
1586 timeline.snapshotCurrentStyles();
1587 }
1588 var style = ast.style;
1589 if (style.type == 5 /* Keyframes */) {
1590 this.visitKeyframes(style, context);
1591 }
1592 else {
1593 context.incrementTime(timings.duration);
1594 this.visitStyle(style, context);
1595 timeline.applyStylesToKeyframe();
1596 }
1597 context.currentAnimateTimings = null;
1598 context.previousNode = ast;
1599 };
1600 AnimationTimelineBuilderVisitor.prototype.visitStyle = function (ast, context) {
1601 var timeline = context.currentTimeline;
1602 var timings = context.currentAnimateTimings;
1603 // this is a special case for when a style() call
1604 // directly follows an animate() call (but not inside of an animate() call)
1605 if (!timings && timeline.getCurrentStyleProperties().length) {
1606 timeline.forwardFrame();
1607 }
1608 var easing = (timings && timings.easing) || ast.easing;
1609 if (ast.isEmptyStep) {
1610 timeline.applyEmptyStep(easing);
1611 }
1612 else {
1613 timeline.setStyles(ast.styles, easing, context.errors, context.options);
1614 }
1615 context.previousNode = ast;
1616 };
1617 AnimationTimelineBuilderVisitor.prototype.visitKeyframes = function (ast, context) {
1618 var currentAnimateTimings = context.currentAnimateTimings;
1619 var startTime = (context.currentTimeline).duration;
1620 var duration = currentAnimateTimings.duration;
1621 var innerContext = context.createSubContext();
1622 var innerTimeline = innerContext.currentTimeline;
1623 innerTimeline.easing = currentAnimateTimings.easing;
1624 ast.styles.forEach(function (step) {
1625 var offset = step.offset || 0;
1626 innerTimeline.forwardTime(offset * duration);
1627 innerTimeline.setStyles(step.styles, step.easing, context.errors, context.options);
1628 innerTimeline.applyStylesToKeyframe();
1629 });
1630 // this will ensure that the parent timeline gets all the styles from
1631 // the child even if the new timeline below is not used
1632 context.currentTimeline.mergeTimelineCollectedStyles(innerTimeline);
1633 // we do this because the window between this timeline and the sub timeline
1634 // should ensure that the styles within are exactly the same as they were before
1635 context.transformIntoNewTimeline(startTime + duration);
1636 context.previousNode = ast;
1637 };
1638 AnimationTimelineBuilderVisitor.prototype.visitQuery = function (ast, context) {
1639 var _this = this;
1640 // in the event that the first step before this is a style step we need
1641 // to ensure the styles are applied before the children are animated
1642 var startTime = context.currentTimeline.currentTime;
1643 var options = (ast.options || {});
1644 var delay = options.delay ? resolveTimingValue(options.delay) : 0;
1645 if (delay && (context.previousNode.type === 6 /* Style */ ||
1646 (startTime == 0 && context.currentTimeline.getCurrentStyleProperties().length))) {
1647 context.currentTimeline.snapshotCurrentStyles();
1648 context.previousNode = DEFAULT_NOOP_PREVIOUS_NODE;
1649 }
1650 var furthestTime = startTime;
1651 var elms = context.invokeQuery(ast.selector, ast.originalSelector, ast.limit, ast.includeSelf, options.optional ? true : false, context.errors);
1652 context.currentQueryTotal = elms.length;
1653 var sameElementTimeline = null;
1654 elms.forEach(function (element, i) {
1655 context.currentQueryIndex = i;
1656 var innerContext = context.createSubContext(ast.options, element);
1657 if (delay) {
1658 innerContext.delayNextStep(delay);
1659 }
1660 if (element === context.element) {
1661 sameElementTimeline = innerContext.currentTimeline;
1662 }
1663 visitDslNode(_this, ast.animation, innerContext);
1664 // this is here just incase the inner steps only contain or end
1665 // with a style() call (which is here to signal that this is a preparatory
1666 // call to style an element before it is animated again)
1667 innerContext.currentTimeline.applyStylesToKeyframe();
1668 var endTime = innerContext.currentTimeline.currentTime;
1669 furthestTime = Math.max(furthestTime, endTime);
1670 });
1671 context.currentQueryIndex = 0;
1672 context.currentQueryTotal = 0;
1673 context.transformIntoNewTimeline(furthestTime);
1674 if (sameElementTimeline) {
1675 context.currentTimeline.mergeTimelineCollectedStyles(sameElementTimeline);
1676 context.currentTimeline.snapshotCurrentStyles();
1677 }
1678 context.previousNode = ast;
1679 };
1680 AnimationTimelineBuilderVisitor.prototype.visitStagger = function (ast, context) {
1681 var parentContext = context.parentContext;
1682 var tl = context.currentTimeline;
1683 var timings = ast.timings;
1684 var duration = Math.abs(timings.duration);
1685 var maxTime = duration * (context.currentQueryTotal - 1);
1686 var delay = duration * context.currentQueryIndex;
1687 var staggerTransformer = timings.duration < 0 ? 'reverse' : timings.easing;
1688 switch (staggerTransformer) {
1689 case 'reverse':
1690 delay = maxTime - delay;
1691 break;
1692 case 'full':
1693 delay = parentContext.currentStaggerTime;
1694 break;
1695 }
1696 var timeline = context.currentTimeline;
1697 if (delay) {
1698 timeline.delayNextStep(delay);
1699 }
1700 var startingTime = timeline.currentTime;
1701 visitDslNode(this, ast.animation, context);
1702 context.previousNode = ast;
1703 // time = duration + delay
1704 // the reason why this computation is so complex is because
1705 // the inner timeline may either have a delay value or a stretched
1706 // keyframe depending on if a subtimeline is not used or is used.
1707 parentContext.currentStaggerTime =
1708 (tl.currentTime - startingTime) + (tl.startTime - parentContext.currentTimeline.startTime);
1709 };
1710 return AnimationTimelineBuilderVisitor;
1711 }());
1712 var DEFAULT_NOOP_PREVIOUS_NODE = {};
1713 var AnimationTimelineContext = /** @class */ (function () {
1714 function AnimationTimelineContext(_driver, element, subInstructions, _enterClassName, _leaveClassName, errors, timelines, initialTimeline) {
1715 this._driver = _driver;
1716 this.element = element;
1717 this.subInstructions = subInstructions;
1718 this._enterClassName = _enterClassName;
1719 this._leaveClassName = _leaveClassName;
1720 this.errors = errors;
1721 this.timelines = timelines;
1722 this.parentContext = null;
1723 this.currentAnimateTimings = null;
1724 this.previousNode = DEFAULT_NOOP_PREVIOUS_NODE;
1725 this.subContextCount = 0;
1726 this.options = {};
1727 this.currentQueryIndex = 0;
1728 this.currentQueryTotal = 0;
1729 this.currentStaggerTime = 0;
1730 this.currentTimeline = initialTimeline || new TimelineBuilder(this._driver, element, 0);
1731 timelines.push(this.currentTimeline);
1732 }
1733 Object.defineProperty(AnimationTimelineContext.prototype, "params", {
1734 get: function () { return this.options.params; },
1735 enumerable: true,
1736 configurable: true
1737 });
1738 AnimationTimelineContext.prototype.updateOptions = function (options, skipIfExists) {
1739 var _this = this;
1740 if (!options)
1741 return;
1742 var newOptions = options;
1743 var optionsToUpdate = this.options;
1744 // NOTE: this will get patched up when other animation methods support duration overrides
1745 if (newOptions.duration != null) {
1746 optionsToUpdate.duration = resolveTimingValue(newOptions.duration);
1747 }
1748 if (newOptions.delay != null) {
1749 optionsToUpdate.delay = resolveTimingValue(newOptions.delay);
1750 }
1751 var newParams = newOptions.params;
1752 if (newParams) {
1753 var paramsToUpdate_1 = optionsToUpdate.params;
1754 if (!paramsToUpdate_1) {
1755 paramsToUpdate_1 = this.options.params = {};
1756 }
1757 Object.keys(newParams).forEach(function (name) {
1758 if (!skipIfExists || !paramsToUpdate_1.hasOwnProperty(name)) {
1759 paramsToUpdate_1[name] = interpolateParams(newParams[name], paramsToUpdate_1, _this.errors);
1760 }
1761 });
1762 }
1763 };
1764 AnimationTimelineContext.prototype._copyOptions = function () {
1765 var options = {};
1766 if (this.options) {
1767 var oldParams_1 = this.options.params;
1768 if (oldParams_1) {
1769 var params_1 = options['params'] = {};
1770 Object.keys(oldParams_1).forEach(function (name) { params_1[name] = oldParams_1[name]; });
1771 }
1772 }
1773 return options;
1774 };
1775 AnimationTimelineContext.prototype.createSubContext = function (options, element, newTime) {
1776 if (options === void 0) { options = null; }
1777 var target = element || this.element;
1778 var context = new AnimationTimelineContext(this._driver, target, this.subInstructions, this._enterClassName, this._leaveClassName, this.errors, this.timelines, this.currentTimeline.fork(target, newTime || 0));
1779 context.previousNode = this.previousNode;
1780 context.currentAnimateTimings = this.currentAnimateTimings;
1781 context.options = this._copyOptions();
1782 context.updateOptions(options);
1783 context.currentQueryIndex = this.currentQueryIndex;
1784 context.currentQueryTotal = this.currentQueryTotal;
1785 context.parentContext = this;
1786 this.subContextCount++;
1787 return context;
1788 };
1789 AnimationTimelineContext.prototype.transformIntoNewTimeline = function (newTime) {
1790 this.previousNode = DEFAULT_NOOP_PREVIOUS_NODE;
1791 this.currentTimeline = this.currentTimeline.fork(this.element, newTime);
1792 this.timelines.push(this.currentTimeline);
1793 return this.currentTimeline;
1794 };
1795 AnimationTimelineContext.prototype.appendInstructionToTimeline = function (instruction, duration, delay) {
1796 var updatedTimings = {
1797 duration: duration != null ? duration : instruction.duration,
1798 delay: this.currentTimeline.currentTime + (delay != null ? delay : 0) + instruction.delay,
1799 easing: ''
1800 };
1801 var builder = new SubTimelineBuilder(this._driver, instruction.element, instruction.keyframes, instruction.preStyleProps, instruction.postStyleProps, updatedTimings, instruction.stretchStartingKeyframe);
1802 this.timelines.push(builder);
1803 return updatedTimings;
1804 };
1805 AnimationTimelineContext.prototype.incrementTime = function (time) {
1806 this.currentTimeline.forwardTime(this.currentTimeline.duration + time);
1807 };
1808 AnimationTimelineContext.prototype.delayNextStep = function (delay) {
1809 // negative delays are not yet supported
1810 if (delay > 0) {
1811 this.currentTimeline.delayNextStep(delay);
1812 }
1813 };
1814 AnimationTimelineContext.prototype.invokeQuery = function (selector, originalSelector, limit, includeSelf, optional, errors) {
1815 var results = [];
1816 if (includeSelf) {
1817 results.push(this.element);
1818 }
1819 if (selector.length > 0) { // if :self is only used then the selector is empty
1820 selector = selector.replace(ENTER_TOKEN_REGEX, '.' + this._enterClassName);
1821 selector = selector.replace(LEAVE_TOKEN_REGEX, '.' + this._leaveClassName);
1822 var multi = limit != 1;
1823 var elements = this._driver.query(this.element, selector, multi);
1824 if (limit !== 0) {
1825 elements = limit < 0 ? elements.slice(elements.length + limit, elements.length) :
1826 elements.slice(0, limit);
1827 }
1828 results.push.apply(results, __spread(elements));
1829 }
1830 if (!optional && results.length == 0) {
1831 errors.push("`query(\"" + originalSelector + "\")` returned zero elements. (Use `query(\"" + originalSelector + "\", { optional: true })` if you wish to allow this.)");
1832 }
1833 return results;
1834 };
1835 return AnimationTimelineContext;
1836 }());
1837 var TimelineBuilder = /** @class */ (function () {
1838 function TimelineBuilder(_driver, element, startTime, _elementTimelineStylesLookup) {
1839 this._driver = _driver;
1840 this.element = element;
1841 this.startTime = startTime;
1842 this._elementTimelineStylesLookup = _elementTimelineStylesLookup;
1843 this.duration = 0;
1844 this._previousKeyframe = {};
1845 this._currentKeyframe = {};
1846 this._keyframes = new Map();
1847 this._styleSummary = {};
1848 this._pendingStyles = {};
1849 this._backFill = {};
1850 this._currentEmptyStepKeyframe = null;
1851 if (!this._elementTimelineStylesLookup) {
1852 this._elementTimelineStylesLookup = new Map();
1853 }
1854 this._localTimelineStyles = Object.create(this._backFill, {});
1855 this._globalTimelineStyles = this._elementTimelineStylesLookup.get(element);
1856 if (!this._globalTimelineStyles) {
1857 this._globalTimelineStyles = this._localTimelineStyles;
1858 this._elementTimelineStylesLookup.set(element, this._localTimelineStyles);
1859 }
1860 this._loadKeyframe();
1861 }
1862 TimelineBuilder.prototype.containsAnimation = function () {
1863 switch (this._keyframes.size) {
1864 case 0:
1865 return false;
1866 case 1:
1867 return this.getCurrentStyleProperties().length > 0;
1868 default:
1869 return true;
1870 }
1871 };
1872 TimelineBuilder.prototype.getCurrentStyleProperties = function () { return Object.keys(this._currentKeyframe); };
1873 Object.defineProperty(TimelineBuilder.prototype, "currentTime", {
1874 get: function () { return this.startTime + this.duration; },
1875 enumerable: true,
1876 configurable: true
1877 });
1878 TimelineBuilder.prototype.delayNextStep = function (delay) {
1879 // in the event that a style() step is placed right before a stagger()
1880 // and that style() step is the very first style() value in the animation
1881 // then we need to make a copy of the keyframe [0, copy, 1] so that the delay
1882 // properly applies the style() values to work with the stagger...
1883 var hasPreStyleStep = this._keyframes.size == 1 && Object.keys(this._pendingStyles).length;
1884 if (this.duration || hasPreStyleStep) {
1885 this.forwardTime(this.currentTime + delay);
1886 if (hasPreStyleStep) {
1887 this.snapshotCurrentStyles();
1888 }
1889 }
1890 else {
1891 this.startTime += delay;
1892 }
1893 };
1894 TimelineBuilder.prototype.fork = function (element, currentTime) {
1895 this.applyStylesToKeyframe();
1896 return new TimelineBuilder(this._driver, element, currentTime || this.currentTime, this._elementTimelineStylesLookup);
1897 };
1898 TimelineBuilder.prototype._loadKeyframe = function () {
1899 if (this._currentKeyframe) {
1900 this._previousKeyframe = this._currentKeyframe;
1901 }
1902 this._currentKeyframe = this._keyframes.get(this.duration);
1903 if (!this._currentKeyframe) {
1904 this._currentKeyframe = Object.create(this._backFill, {});
1905 this._keyframes.set(this.duration, this._currentKeyframe);
1906 }
1907 };
1908 TimelineBuilder.prototype.forwardFrame = function () {
1909 this.duration += ONE_FRAME_IN_MILLISECONDS;
1910 this._loadKeyframe();
1911 };
1912 TimelineBuilder.prototype.forwardTime = function (time) {
1913 this.applyStylesToKeyframe();
1914 this.duration = time;
1915 this._loadKeyframe();
1916 };
1917 TimelineBuilder.prototype._updateStyle = function (prop, value) {
1918 this._localTimelineStyles[prop] = value;
1919 this._globalTimelineStyles[prop] = value;
1920 this._styleSummary[prop] = { time: this.currentTime, value: value };
1921 };
1922 TimelineBuilder.prototype.allowOnlyTimelineStyles = function () { return this._currentEmptyStepKeyframe !== this._currentKeyframe; };
1923 TimelineBuilder.prototype.applyEmptyStep = function (easing) {
1924 var _this = this;
1925 if (easing) {
1926 this._previousKeyframe['easing'] = easing;
1927 }
1928 // special case for animate(duration):
1929 // all missing styles are filled with a `*` value then
1930 // if any destination styles are filled in later on the same
1931 // keyframe then they will override the overridden styles
1932 // We use `_globalTimelineStyles` here because there may be
1933 // styles in previous keyframes that are not present in this timeline
1934 Object.keys(this._globalTimelineStyles).forEach(function (prop) {
1935 _this._backFill[prop] = _this._globalTimelineStyles[prop] || animations.AUTO_STYLE;
1936 _this._currentKeyframe[prop] = animations.AUTO_STYLE;
1937 });
1938 this._currentEmptyStepKeyframe = this._currentKeyframe;
1939 };
1940 TimelineBuilder.prototype.setStyles = function (input, easing, errors, options) {
1941 var _this = this;
1942 if (easing) {
1943 this._previousKeyframe['easing'] = easing;
1944 }
1945 var params = (options && options.params) || {};
1946 var styles = flattenStyles(input, this._globalTimelineStyles);
1947 Object.keys(styles).forEach(function (prop) {
1948 var val = interpolateParams(styles[prop], params, errors);
1949 _this._pendingStyles[prop] = val;
1950 if (!_this._localTimelineStyles.hasOwnProperty(prop)) {
1951 _this._backFill[prop] = _this._globalTimelineStyles.hasOwnProperty(prop) ?
1952 _this._globalTimelineStyles[prop] :
1953 animations.AUTO_STYLE;
1954 }
1955 _this._updateStyle(prop, val);
1956 });
1957 };
1958 TimelineBuilder.prototype.applyStylesToKeyframe = function () {
1959 var _this = this;
1960 var styles = this._pendingStyles;
1961 var props = Object.keys(styles);
1962 if (props.length == 0)
1963 return;
1964 this._pendingStyles = {};
1965 props.forEach(function (prop) {
1966 var val = styles[prop];
1967 _this._currentKeyframe[prop] = val;
1968 });
1969 Object.keys(this._localTimelineStyles).forEach(function (prop) {
1970 if (!_this._currentKeyframe.hasOwnProperty(prop)) {
1971 _this._currentKeyframe[prop] = _this._localTimelineStyles[prop];
1972 }
1973 });
1974 };
1975 TimelineBuilder.prototype.snapshotCurrentStyles = function () {
1976 var _this = this;
1977 Object.keys(this._localTimelineStyles).forEach(function (prop) {
1978 var val = _this._localTimelineStyles[prop];
1979 _this._pendingStyles[prop] = val;
1980 _this._updateStyle(prop, val);
1981 });
1982 };
1983 TimelineBuilder.prototype.getFinalKeyframe = function () { return this._keyframes.get(this.duration); };
1984 Object.defineProperty(TimelineBuilder.prototype, "properties", {
1985 get: function () {
1986 var properties = [];
1987 for (var prop in this._currentKeyframe) {
1988 properties.push(prop);
1989 }
1990 return properties;
1991 },
1992 enumerable: true,
1993 configurable: true
1994 });
1995 TimelineBuilder.prototype.mergeTimelineCollectedStyles = function (timeline) {
1996 var _this = this;
1997 Object.keys(timeline._styleSummary).forEach(function (prop) {
1998 var details0 = _this._styleSummary[prop];
1999 var details1 = timeline._styleSummary[prop];
2000 if (!details0 || details1.time > details0.time) {
2001 _this._updateStyle(prop, details1.value);
2002 }
2003 });
2004 };
2005 TimelineBuilder.prototype.buildKeyframes = function () {
2006 var _this = this;
2007 this.applyStylesToKeyframe();
2008 var preStyleProps = new Set();
2009 var postStyleProps = new Set();
2010 var isEmpty = this._keyframes.size === 1 && this.duration === 0;
2011 var finalKeyframes = [];
2012 this._keyframes.forEach(function (keyframe, time) {
2013 var finalKeyframe = copyStyles(keyframe, true);
2014 Object.keys(finalKeyframe).forEach(function (prop) {
2015 var value = finalKeyframe[prop];
2016 if (value == animations.ɵPRE_STYLE) {
2017 preStyleProps.add(prop);
2018 }
2019 else if (value == animations.AUTO_STYLE) {
2020 postStyleProps.add(prop);
2021 }
2022 });
2023 if (!isEmpty) {
2024 finalKeyframe['offset'] = time / _this.duration;
2025 }
2026 finalKeyframes.push(finalKeyframe);
2027 });
2028 var preProps = preStyleProps.size ? iteratorToArray(preStyleProps.values()) : [];
2029 var postProps = postStyleProps.size ? iteratorToArray(postStyleProps.values()) : [];
2030 // special case for a 0-second animation (which is designed just to place styles onscreen)
2031 if (isEmpty) {
2032 var kf0 = finalKeyframes[0];
2033 var kf1 = copyObj(kf0);
2034 kf0['offset'] = 0;
2035 kf1['offset'] = 1;
2036 finalKeyframes = [kf0, kf1];
2037 }
2038 return createTimelineInstruction(this.element, finalKeyframes, preProps, postProps, this.duration, this.startTime, this.easing, false);
2039 };
2040 return TimelineBuilder;
2041 }());
2042 var SubTimelineBuilder = /** @class */ (function (_super) {
2043 __extends(SubTimelineBuilder, _super);
2044 function SubTimelineBuilder(driver, element, keyframes, preStyleProps, postStyleProps, timings, _stretchStartingKeyframe) {
2045 if (_stretchStartingKeyframe === void 0) { _stretchStartingKeyframe = false; }
2046 var _this = _super.call(this, driver, element, timings.delay) || this;
2047 _this.element = element;
2048 _this.keyframes = keyframes;
2049 _this.preStyleProps = preStyleProps;
2050 _this.postStyleProps = postStyleProps;
2051 _this._stretchStartingKeyframe = _stretchStartingKeyframe;
2052 _this.timings = { duration: timings.duration, delay: timings.delay, easing: timings.easing };
2053 return _this;
2054 }
2055 SubTimelineBuilder.prototype.containsAnimation = function () { return this.keyframes.length > 1; };
2056 SubTimelineBuilder.prototype.buildKeyframes = function () {
2057 var keyframes = this.keyframes;
2058 var _a = this.timings, delay = _a.delay, duration = _a.duration, easing = _a.easing;
2059 if (this._stretchStartingKeyframe && delay) {
2060 var newKeyframes = [];
2061 var totalTime = duration + delay;
2062 var startingGap = delay / totalTime;
2063 // the original starting keyframe now starts once the delay is done
2064 var newFirstKeyframe = copyStyles(keyframes[0], false);
2065 newFirstKeyframe['offset'] = 0;
2066 newKeyframes.push(newFirstKeyframe);
2067 var oldFirstKeyframe = copyStyles(keyframes[0], false);
2068 oldFirstKeyframe['offset'] = roundOffset(startingGap);
2069 newKeyframes.push(oldFirstKeyframe);
2070 /*
2071 When the keyframe is stretched then it means that the delay before the animation
2072 starts is gone. Instead the first keyframe is placed at the start of the animation
2073 and it is then copied to where it starts when the original delay is over. This basically
2074 means nothing animates during that delay, but the styles are still renderered. For this
2075 to work the original offset values that exist in the original keyframes must be "warped"
2076 so that they can take the new keyframe + delay into account.
2077
2078 delay=1000, duration=1000, keyframes = 0 .5 1
2079
2080 turns into
2081
2082 delay=0, duration=2000, keyframes = 0 .33 .66 1
2083 */
2084 // offsets between 1 ... n -1 are all warped by the keyframe stretch
2085 var limit = keyframes.length - 1;
2086 for (var i = 1; i <= limit; i++) {
2087 var kf = copyStyles(keyframes[i], false);
2088 var oldOffset = kf['offset'];
2089 var timeAtKeyframe = delay + oldOffset * duration;
2090 kf['offset'] = roundOffset(timeAtKeyframe / totalTime);
2091 newKeyframes.push(kf);
2092 }
2093 // the new starting keyframe should be added at the start
2094 duration = totalTime;
2095 delay = 0;
2096 easing = '';
2097 keyframes = newKeyframes;
2098 }
2099 return createTimelineInstruction(this.element, keyframes, this.preStyleProps, this.postStyleProps, duration, delay, easing, true);
2100 };
2101 return SubTimelineBuilder;
2102 }(TimelineBuilder));
2103 function roundOffset(offset, decimalPoints) {
2104 if (decimalPoints === void 0) { decimalPoints = 3; }
2105 var mult = Math.pow(10, decimalPoints - 1);
2106 return Math.round(offset * mult) / mult;
2107 }
2108 function flattenStyles(input, allStyles) {
2109 var styles = {};
2110 var allProperties;
2111 input.forEach(function (token) {
2112 if (token === '*') {
2113 allProperties = allProperties || Object.keys(allStyles);
2114 allProperties.forEach(function (prop) { styles[prop] = animations.AUTO_STYLE; });
2115 }
2116 else {
2117 copyStyles(token, false, styles);
2118 }
2119 });
2120 return styles;
2121 }
2122
2123 var Animation = /** @class */ (function () {
2124 function Animation(_driver, input) {
2125 this._driver = _driver;
2126 var errors = [];
2127 var ast = buildAnimationAst(_driver, input, errors);
2128 if (errors.length) {
2129 var errorMessage = "animation validation failed:\n" + errors.join("\n");
2130 throw new Error(errorMessage);
2131 }
2132 this._animationAst = ast;
2133 }
2134 Animation.prototype.buildTimelines = function (element, startingStyles, destinationStyles, options, subInstructions) {
2135 var start = Array.isArray(startingStyles) ? normalizeStyles(startingStyles) :
2136 startingStyles;
2137 var dest = Array.isArray(destinationStyles) ? normalizeStyles(destinationStyles) :
2138 destinationStyles;
2139 var errors = [];
2140 subInstructions = subInstructions || new ElementInstructionMap();
2141 var result = buildAnimationTimelines(this._driver, element, this._animationAst, ENTER_CLASSNAME, LEAVE_CLASSNAME, start, dest, options, subInstructions, errors);
2142 if (errors.length) {
2143 var errorMessage = "animation building failed:\n" + errors.join("\n");
2144 throw new Error(errorMessage);
2145 }
2146 return result;
2147 };
2148 return Animation;
2149 }());
2150
2151 /**
2152 * @license
2153 * Copyright Google Inc. All Rights Reserved.
2154 *
2155 * Use of this source code is governed by an MIT-style license that can be
2156 * found in the LICENSE file at https://angular.io/license
2157 */
2158 /**
2159 * @publicApi
2160 */
2161 var AnimationStyleNormalizer = /** @class */ (function () {
2162 function AnimationStyleNormalizer() {
2163 }
2164 return AnimationStyleNormalizer;
2165 }());
2166 /**
2167 * @publicApi
2168 */
2169 var NoopAnimationStyleNormalizer = /** @class */ (function () {
2170 function NoopAnimationStyleNormalizer() {
2171 }
2172 NoopAnimationStyleNormalizer.prototype.normalizePropertyName = function (propertyName, errors) { return propertyName; };
2173 NoopAnimationStyleNormalizer.prototype.normalizeStyleValue = function (userProvidedProperty, normalizedProperty, value, errors) {
2174 return value;
2175 };
2176 return NoopAnimationStyleNormalizer;
2177 }());
2178
2179 var WebAnimationsStyleNormalizer = /** @class */ (function (_super) {
2180 __extends(WebAnimationsStyleNormalizer, _super);
2181 function WebAnimationsStyleNormalizer() {
2182 return _super !== null && _super.apply(this, arguments) || this;
2183 }
2184 WebAnimationsStyleNormalizer.prototype.normalizePropertyName = function (propertyName, errors) {
2185 return dashCaseToCamelCase(propertyName);
2186 };
2187 WebAnimationsStyleNormalizer.prototype.normalizeStyleValue = function (userProvidedProperty, normalizedProperty, value, errors) {
2188 var unit = '';
2189 var strVal = value.toString().trim();
2190 if (DIMENSIONAL_PROP_MAP[normalizedProperty] && value !== 0 && value !== '0') {
2191 if (typeof value === 'number') {
2192 unit = 'px';
2193 }
2194 else {
2195 var valAndSuffixMatch = value.match(/^[+-]?[\d\.]+([a-z]*)$/);
2196 if (valAndSuffixMatch && valAndSuffixMatch[1].length == 0) {
2197 errors.push("Please provide a CSS unit value for " + userProvidedProperty + ":" + value);
2198 }
2199 }
2200 }
2201 return strVal + unit;
2202 };
2203 return WebAnimationsStyleNormalizer;
2204 }(AnimationStyleNormalizer));
2205 var ɵ0$1 = function () { return 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'
2206 .split(',')); };
2207 var DIMENSIONAL_PROP_MAP = (ɵ0$1)();
2208 function makeBooleanMap(keys) {
2209 var map = {};
2210 keys.forEach(function (key) { return map[key] = true; });
2211 return map;
2212 }
2213
2214 function createTransitionInstruction(element, triggerName, fromState, toState, isRemovalTransition, fromStyles, toStyles, timelines, queriedElements, preStyleProps, postStyleProps, totalTime, errors) {
2215 return {
2216 type: 0 /* TransitionAnimation */,
2217 element: element,
2218 triggerName: triggerName,
2219 isRemovalTransition: isRemovalTransition,
2220 fromState: fromState,
2221 fromStyles: fromStyles,
2222 toState: toState,
2223 toStyles: toStyles,
2224 timelines: timelines,
2225 queriedElements: queriedElements,
2226 preStyleProps: preStyleProps,
2227 postStyleProps: postStyleProps,
2228 totalTime: totalTime,
2229 errors: errors
2230 };
2231 }
2232
2233 var EMPTY_OBJECT = {};
2234 var AnimationTransitionFactory = /** @class */ (function () {
2235 function AnimationTransitionFactory(_triggerName, ast, _stateStyles) {
2236 this._triggerName = _triggerName;
2237 this.ast = ast;
2238 this._stateStyles = _stateStyles;
2239 }
2240 AnimationTransitionFactory.prototype.match = function (currentState, nextState, element, params) {
2241 return oneOrMoreTransitionsMatch(this.ast.matchers, currentState, nextState, element, params);
2242 };
2243 AnimationTransitionFactory.prototype.buildStyles = function (stateName, params, errors) {
2244 var backupStateStyler = this._stateStyles['*'];
2245 var stateStyler = this._stateStyles[stateName];
2246 var backupStyles = backupStateStyler ? backupStateStyler.buildStyles(params, errors) : {};
2247 return stateStyler ? stateStyler.buildStyles(params, errors) : backupStyles;
2248 };
2249 AnimationTransitionFactory.prototype.build = function (driver, element, currentState, nextState, enterClassName, leaveClassName, currentOptions, nextOptions, subInstructions, skipAstBuild) {
2250 var errors = [];
2251 var transitionAnimationParams = this.ast.options && this.ast.options.params || EMPTY_OBJECT;
2252 var currentAnimationParams = currentOptions && currentOptions.params || EMPTY_OBJECT;
2253 var currentStateStyles = this.buildStyles(currentState, currentAnimationParams, errors);
2254 var nextAnimationParams = nextOptions && nextOptions.params || EMPTY_OBJECT;
2255 var nextStateStyles = this.buildStyles(nextState, nextAnimationParams, errors);
2256 var queriedElements = new Set();
2257 var preStyleMap = new Map();
2258 var postStyleMap = new Map();
2259 var isRemoval = nextState === 'void';
2260 var animationOptions = { params: __assign({}, transitionAnimationParams, nextAnimationParams) };
2261 var timelines = skipAstBuild ? [] : buildAnimationTimelines(driver, element, this.ast.animation, enterClassName, leaveClassName, currentStateStyles, nextStateStyles, animationOptions, subInstructions, errors);
2262 var totalTime = 0;
2263 timelines.forEach(function (tl) { totalTime = Math.max(tl.duration + tl.delay, totalTime); });
2264 if (errors.length) {
2265 return createTransitionInstruction(element, this._triggerName, currentState, nextState, isRemoval, currentStateStyles, nextStateStyles, [], [], preStyleMap, postStyleMap, totalTime, errors);
2266 }
2267 timelines.forEach(function (tl) {
2268 var elm = tl.element;
2269 var preProps = getOrSetAsInMap(preStyleMap, elm, {});
2270 tl.preStyleProps.forEach(function (prop) { return preProps[prop] = true; });
2271 var postProps = getOrSetAsInMap(postStyleMap, elm, {});
2272 tl.postStyleProps.forEach(function (prop) { return postProps[prop] = true; });
2273 if (elm !== element) {
2274 queriedElements.add(elm);
2275 }
2276 });
2277 var queriedElementsList = iteratorToArray(queriedElements.values());
2278 return createTransitionInstruction(element, this._triggerName, currentState, nextState, isRemoval, currentStateStyles, nextStateStyles, timelines, queriedElementsList, preStyleMap, postStyleMap, totalTime);
2279 };
2280 return AnimationTransitionFactory;
2281 }());
2282 function oneOrMoreTransitionsMatch(matchFns, currentState, nextState, element, params) {
2283 return matchFns.some(function (fn) { return fn(currentState, nextState, element, params); });
2284 }
2285 var AnimationStateStyles = /** @class */ (function () {
2286 function AnimationStateStyles(styles, defaultParams) {
2287 this.styles = styles;
2288 this.defaultParams = defaultParams;
2289 }
2290 AnimationStateStyles.prototype.buildStyles = function (params, errors) {
2291 var finalStyles = {};
2292 var combinedParams = copyObj(this.defaultParams);
2293 Object.keys(params).forEach(function (key) {
2294 var value = params[key];
2295 if (value != null) {
2296 combinedParams[key] = value;
2297 }
2298 });
2299 this.styles.styles.forEach(function (value) {
2300 if (typeof value !== 'string') {
2301 var styleObj_1 = value;
2302 Object.keys(styleObj_1).forEach(function (prop) {
2303 var val = styleObj_1[prop];
2304 if (val.length > 1) {
2305 val = interpolateParams(val, combinedParams, errors);
2306 }
2307 finalStyles[prop] = val;
2308 });
2309 }
2310 });
2311 return finalStyles;
2312 };
2313 return AnimationStateStyles;
2314 }());
2315
2316 /**
2317 * @publicApi
2318 */
2319 function buildTrigger(name, ast) {
2320 return new AnimationTrigger(name, ast);
2321 }
2322 /**
2323 * @publicApi
2324 */
2325 var AnimationTrigger = /** @class */ (function () {
2326 function AnimationTrigger(name, ast) {
2327 var _this = this;
2328 this.name = name;
2329 this.ast = ast;
2330 this.transitionFactories = [];
2331 this.states = {};
2332 ast.states.forEach(function (ast) {
2333 var defaultParams = (ast.options && ast.options.params) || {};
2334 _this.states[ast.name] = new AnimationStateStyles(ast.style, defaultParams);
2335 });
2336 balanceProperties(this.states, 'true', '1');
2337 balanceProperties(this.states, 'false', '0');
2338 ast.transitions.forEach(function (ast) {
2339 _this.transitionFactories.push(new AnimationTransitionFactory(name, ast, _this.states));
2340 });
2341 this.fallbackTransition = createFallbackTransition(name, this.states);
2342 }
2343 Object.defineProperty(AnimationTrigger.prototype, "containsQueries", {
2344 get: function () { return this.ast.queryCount > 0; },
2345 enumerable: true,
2346 configurable: true
2347 });
2348 AnimationTrigger.prototype.matchTransition = function (currentState, nextState, element, params) {
2349 var entry = this.transitionFactories.find(function (f) { return f.match(currentState, nextState, element, params); });
2350 return entry || null;
2351 };
2352 AnimationTrigger.prototype.matchStyles = function (currentState, params, errors) {
2353 return this.fallbackTransition.buildStyles(currentState, params, errors);
2354 };
2355 return AnimationTrigger;
2356 }());
2357 function createFallbackTransition(triggerName, states) {
2358 var matchers = [function (fromState, toState) { return true; }];
2359 var animation = { type: 2 /* Sequence */, steps: [], options: null };
2360 var transition = {
2361 type: 1 /* Transition */,
2362 animation: animation,
2363 matchers: matchers,
2364 options: null,
2365 queryCount: 0,
2366 depCount: 0
2367 };
2368 return new AnimationTransitionFactory(triggerName, transition, states);
2369 }
2370 function balanceProperties(obj, key1, key2) {
2371 if (obj.hasOwnProperty(key1)) {
2372 if (!obj.hasOwnProperty(key2)) {
2373 obj[key2] = obj[key1];
2374 }
2375 }
2376 else if (obj.hasOwnProperty(key2)) {
2377 obj[key1] = obj[key2];
2378 }
2379 }
2380
2381 /**
2382 * @license
2383 * Copyright Google Inc. All Rights Reserved.
2384 *
2385 * Use of this source code is governed by an MIT-style license that can be
2386 * found in the LICENSE file at https://angular.io/license
2387 */
2388 var EMPTY_INSTRUCTION_MAP = new ElementInstructionMap();
2389 var TimelineAnimationEngine = /** @class */ (function () {
2390 function TimelineAnimationEngine(bodyNode, _driver, _normalizer) {
2391 this.bodyNode = bodyNode;
2392 this._driver = _driver;
2393 this._normalizer = _normalizer;
2394 this._animations = {};
2395 this._playersById = {};
2396 this.players = [];
2397 }
2398 TimelineAnimationEngine.prototype.register = function (id, metadata) {
2399 var errors = [];
2400 var ast = buildAnimationAst(this._driver, metadata, errors);
2401 if (errors.length) {
2402 throw new Error("Unable to build the animation due to the following errors: " + errors.join("\n"));
2403 }
2404 else {
2405 this._animations[id] = ast;
2406 }
2407 };
2408 TimelineAnimationEngine.prototype._buildPlayer = function (i, preStyles, postStyles) {
2409 var element = i.element;
2410 var keyframes = normalizeKeyframes(this._driver, this._normalizer, element, i.keyframes, preStyles, postStyles);
2411 return this._driver.animate(element, keyframes, i.duration, i.delay, i.easing, [], true);
2412 };
2413 TimelineAnimationEngine.prototype.create = function (id, element, options) {
2414 var _this = this;
2415 if (options === void 0) { options = {}; }
2416 var errors = [];
2417 var ast = this._animations[id];
2418 var instructions;
2419 var autoStylesMap = new Map();
2420 if (ast) {
2421 instructions = buildAnimationTimelines(this._driver, element, ast, ENTER_CLASSNAME, LEAVE_CLASSNAME, {}, {}, options, EMPTY_INSTRUCTION_MAP, errors);
2422 instructions.forEach(function (inst) {
2423 var styles = getOrSetAsInMap(autoStylesMap, inst.element, {});
2424 inst.postStyleProps.forEach(function (prop) { return styles[prop] = null; });
2425 });
2426 }
2427 else {
2428 errors.push('The requested animation doesn\'t exist or has already been destroyed');
2429 instructions = [];
2430 }
2431 if (errors.length) {
2432 throw new Error("Unable to create the animation due to the following errors: " + errors.join("\n"));
2433 }
2434 autoStylesMap.forEach(function (styles, element) {
2435 Object.keys(styles).forEach(function (prop) { styles[prop] = _this._driver.computeStyle(element, prop, animations.AUTO_STYLE); });
2436 });
2437 var players = instructions.map(function (i) {
2438 var styles = autoStylesMap.get(i.element);
2439 return _this._buildPlayer(i, {}, styles);
2440 });
2441 var player = optimizeGroupPlayer(players);
2442 this._playersById[id] = player;
2443 player.onDestroy(function () { return _this.destroy(id); });
2444 this.players.push(player);
2445 return player;
2446 };
2447 TimelineAnimationEngine.prototype.destroy = function (id) {
2448 var player = this._getPlayer(id);
2449 player.destroy();
2450 delete this._playersById[id];
2451 var index = this.players.indexOf(player);
2452 if (index >= 0) {
2453 this.players.splice(index, 1);
2454 }
2455 };
2456 TimelineAnimationEngine.prototype._getPlayer = function (id) {
2457 var player = this._playersById[id];
2458 if (!player) {
2459 throw new Error("Unable to find the timeline player referenced by " + id);
2460 }
2461 return player;
2462 };
2463 TimelineAnimationEngine.prototype.listen = function (id, element, eventName, callback) {
2464 // triggerName, fromState, toState are all ignored for timeline animations
2465 var baseEvent = makeAnimationEvent(element, '', '', '');
2466 listenOnPlayer(this._getPlayer(id), eventName, baseEvent, callback);
2467 return function () { };
2468 };
2469 TimelineAnimationEngine.prototype.command = function (id, element, command, args) {
2470 if (command == 'register') {
2471 this.register(id, args[0]);
2472 return;
2473 }
2474 if (command == 'create') {
2475 var options = (args[0] || {});
2476 this.create(id, element, options);
2477 return;
2478 }
2479 var player = this._getPlayer(id);
2480 switch (command) {
2481 case 'play':
2482 player.play();
2483 break;
2484 case 'pause':
2485 player.pause();
2486 break;
2487 case 'reset':
2488 player.reset();
2489 break;
2490 case 'restart':
2491 player.restart();
2492 break;
2493 case 'finish':
2494 player.finish();
2495 break;
2496 case 'init':
2497 player.init();
2498 break;
2499 case 'setPosition':
2500 player.setPosition(parseFloat(args[0]));
2501 break;
2502 case 'destroy':
2503 this.destroy(id);
2504 break;
2505 }
2506 };
2507 return TimelineAnimationEngine;
2508 }());
2509
2510 var QUEUED_CLASSNAME = 'ng-animate-queued';
2511 var QUEUED_SELECTOR = '.ng-animate-queued';
2512 var DISABLED_CLASSNAME = 'ng-animate-disabled';
2513 var DISABLED_SELECTOR = '.ng-animate-disabled';
2514 var STAR_CLASSNAME = 'ng-star-inserted';
2515 var STAR_SELECTOR = '.ng-star-inserted';
2516 var EMPTY_PLAYER_ARRAY = [];
2517 var NULL_REMOVAL_STATE = {
2518 namespaceId: '',
2519 setForRemoval: false,
2520 setForMove: false,
2521 hasAnimation: false,
2522 removedBeforeQueried: false
2523 };
2524 var NULL_REMOVED_QUERIED_STATE = {
2525 namespaceId: '',
2526 setForMove: false,
2527 setForRemoval: false,
2528 hasAnimation: false,
2529 removedBeforeQueried: true
2530 };
2531 var REMOVAL_FLAG = '__ng_removed';
2532 var StateValue = /** @class */ (function () {
2533 function StateValue(input, namespaceId) {
2534 if (namespaceId === void 0) { namespaceId = ''; }
2535 this.namespaceId = namespaceId;
2536 var isObj = input && input.hasOwnProperty('value');
2537 var value = isObj ? input['value'] : input;
2538 this.value = normalizeTriggerValue(value);
2539 if (isObj) {
2540 var options = copyObj(input);
2541 delete options['value'];
2542 this.options = options;
2543 }
2544 else {
2545 this.options = {};
2546 }
2547 if (!this.options.params) {
2548 this.options.params = {};
2549 }
2550 }
2551 Object.defineProperty(StateValue.prototype, "params", {
2552 get: function () { return this.options.params; },
2553 enumerable: true,
2554 configurable: true
2555 });
2556 StateValue.prototype.absorbOptions = function (options) {
2557 var newParams = options.params;
2558 if (newParams) {
2559 var oldParams_1 = this.options.params;
2560 Object.keys(newParams).forEach(function (prop) {
2561 if (oldParams_1[prop] == null) {
2562 oldParams_1[prop] = newParams[prop];
2563 }
2564 });
2565 }
2566 };
2567 return StateValue;
2568 }());
2569 var VOID_VALUE = 'void';
2570 var DEFAULT_STATE_VALUE = new StateValue(VOID_VALUE);
2571 var AnimationTransitionNamespace = /** @class */ (function () {
2572 function AnimationTransitionNamespace(id, hostElement, _engine) {
2573 this.id = id;
2574 this.hostElement = hostElement;
2575 this._engine = _engine;
2576 this.players = [];
2577 this._triggers = {};
2578 this._queue = [];
2579 this._elementListeners = new Map();
2580 this._hostClassName = 'ng-tns-' + id;
2581 addClass(hostElement, this._hostClassName);
2582 }
2583 AnimationTransitionNamespace.prototype.listen = function (element, name, phase, callback) {
2584 var _this = this;
2585 if (!this._triggers.hasOwnProperty(name)) {
2586 throw new Error("Unable to listen on the animation trigger event \"" + phase + "\" because the animation trigger \"" + name + "\" doesn't exist!");
2587 }
2588 if (phase == null || phase.length == 0) {
2589 throw new Error("Unable to listen on the animation trigger \"" + name + "\" because the provided event is undefined!");
2590 }
2591 if (!isTriggerEventValid(phase)) {
2592 throw new Error("The provided animation trigger event \"" + phase + "\" for the animation trigger \"" + name + "\" is not supported!");
2593 }
2594 var listeners = getOrSetAsInMap(this._elementListeners, element, []);
2595 var data = { name: name, phase: phase, callback: callback };
2596 listeners.push(data);
2597 var triggersWithStates = getOrSetAsInMap(this._engine.statesByElement, element, {});
2598 if (!triggersWithStates.hasOwnProperty(name)) {
2599 addClass(element, NG_TRIGGER_CLASSNAME);
2600 addClass(element, NG_TRIGGER_CLASSNAME + '-' + name);
2601 triggersWithStates[name] = DEFAULT_STATE_VALUE;
2602 }
2603 return function () {
2604 // the event listener is removed AFTER the flush has occurred such
2605 // that leave animations callbacks can fire (otherwise if the node
2606 // is removed in between then the listeners would be deregistered)
2607 _this._engine.afterFlush(function () {
2608 var index = listeners.indexOf(data);
2609 if (index >= 0) {
2610 listeners.splice(index, 1);
2611 }
2612 if (!_this._triggers[name]) {
2613 delete triggersWithStates[name];
2614 }
2615 });
2616 };
2617 };
2618 AnimationTransitionNamespace.prototype.register = function (name, ast) {
2619 if (this._triggers[name]) {
2620 // throw
2621 return false;
2622 }
2623 else {
2624 this._triggers[name] = ast;
2625 return true;
2626 }
2627 };
2628 AnimationTransitionNamespace.prototype._getTrigger = function (name) {
2629 var trigger = this._triggers[name];
2630 if (!trigger) {
2631 throw new Error("The provided animation trigger \"" + name + "\" has not been registered!");
2632 }
2633 return trigger;
2634 };
2635 AnimationTransitionNamespace.prototype.trigger = function (element, triggerName, value, defaultToFallback) {
2636 var _this = this;
2637 if (defaultToFallback === void 0) { defaultToFallback = true; }
2638 var trigger = this._getTrigger(triggerName);
2639 var player = new TransitionAnimationPlayer(this.id, triggerName, element);
2640 var triggersWithStates = this._engine.statesByElement.get(element);
2641 if (!triggersWithStates) {
2642 addClass(element, NG_TRIGGER_CLASSNAME);
2643 addClass(element, NG_TRIGGER_CLASSNAME + '-' + triggerName);
2644 this._engine.statesByElement.set(element, triggersWithStates = {});
2645 }
2646 var fromState = triggersWithStates[triggerName];
2647 var toState = new StateValue(value, this.id);
2648 var isObj = value && value.hasOwnProperty('value');
2649 if (!isObj && fromState) {
2650 toState.absorbOptions(fromState.options);
2651 }
2652 triggersWithStates[triggerName] = toState;
2653 if (!fromState) {
2654 fromState = DEFAULT_STATE_VALUE;
2655 }
2656 var isRemoval = toState.value === VOID_VALUE;
2657 // normally this isn't reached by here, however, if an object expression
2658 // is passed in then it may be a new object each time. Comparing the value
2659 // is important since that will stay the same despite there being a new object.
2660 // The removal arc here is special cased because the same element is triggered
2661 // twice in the event that it contains animations on the outer/inner portions
2662 // of the host container
2663 if (!isRemoval && fromState.value === toState.value) {
2664 // this means that despite the value not changing, some inner params
2665 // have changed which means that the animation final styles need to be applied
2666 if (!objEquals(fromState.params, toState.params)) {
2667 var errors = [];
2668 var fromStyles_1 = trigger.matchStyles(fromState.value, fromState.params, errors);
2669 var toStyles_1 = trigger.matchStyles(toState.value, toState.params, errors);
2670 if (errors.length) {
2671 this._engine.reportError(errors);
2672 }
2673 else {
2674 this._engine.afterFlush(function () {
2675 eraseStyles(element, fromStyles_1);
2676 setStyles(element, toStyles_1);
2677 });
2678 }
2679 }
2680 return;
2681 }
2682 var playersOnElement = getOrSetAsInMap(this._engine.playersByElement, element, []);
2683 playersOnElement.forEach(function (player) {
2684 // only remove the player if it is queued on the EXACT same trigger/namespace
2685 // we only also deal with queued players here because if the animation has
2686 // started then we want to keep the player alive until the flush happens
2687 // (which is where the previousPlayers are passed into the new palyer)
2688 if (player.namespaceId == _this.id && player.triggerName == triggerName && player.queued) {
2689 player.destroy();
2690 }
2691 });
2692 var transition = trigger.matchTransition(fromState.value, toState.value, element, toState.params);
2693 var isFallbackTransition = false;
2694 if (!transition) {
2695 if (!defaultToFallback)
2696 return;
2697 transition = trigger.fallbackTransition;
2698 isFallbackTransition = true;
2699 }
2700 this._engine.totalQueuedPlayers++;
2701 this._queue.push({ element: element, triggerName: triggerName, transition: transition, fromState: fromState, toState: toState, player: player, isFallbackTransition: isFallbackTransition });
2702 if (!isFallbackTransition) {
2703 addClass(element, QUEUED_CLASSNAME);
2704 player.onStart(function () { removeClass(element, QUEUED_CLASSNAME); });
2705 }
2706 player.onDone(function () {
2707 var index = _this.players.indexOf(player);
2708 if (index >= 0) {
2709 _this.players.splice(index, 1);
2710 }
2711 var players = _this._engine.playersByElement.get(element);
2712 if (players) {
2713 var index_1 = players.indexOf(player);
2714 if (index_1 >= 0) {
2715 players.splice(index_1, 1);
2716 }
2717 }
2718 });
2719 this.players.push(player);
2720 playersOnElement.push(player);
2721 return player;
2722 };
2723 AnimationTransitionNamespace.prototype.deregister = function (name) {
2724 var _this = this;
2725 delete this._triggers[name];
2726 this._engine.statesByElement.forEach(function (stateMap, element) { delete stateMap[name]; });
2727 this._elementListeners.forEach(function (listeners, element) {
2728 _this._elementListeners.set(element, listeners.filter(function (entry) { return entry.name != name; }));
2729 });
2730 };
2731 AnimationTransitionNamespace.prototype.clearElementCache = function (element) {
2732 this._engine.statesByElement.delete(element);
2733 this._elementListeners.delete(element);
2734 var elementPlayers = this._engine.playersByElement.get(element);
2735 if (elementPlayers) {
2736 elementPlayers.forEach(function (player) { return player.destroy(); });
2737 this._engine.playersByElement.delete(element);
2738 }
2739 };
2740 AnimationTransitionNamespace.prototype._signalRemovalForInnerTriggers = function (rootElement, context, animate) {
2741 var _this = this;
2742 if (animate === void 0) { animate = false; }
2743 // emulate a leave animation for all inner nodes within this node.
2744 // If there are no animations found for any of the nodes then clear the cache
2745 // for the element.
2746 this._engine.driver.query(rootElement, NG_TRIGGER_SELECTOR, true).forEach(function (elm) {
2747 // this means that an inner remove() operation has already kicked off
2748 // the animation on this element...
2749 if (elm[REMOVAL_FLAG])
2750 return;
2751 var namespaces = _this._engine.fetchNamespacesByElement(elm);
2752 if (namespaces.size) {
2753 namespaces.forEach(function (ns) { return ns.triggerLeaveAnimation(elm, context, false, true); });
2754 }
2755 else {
2756 _this.clearElementCache(elm);
2757 }
2758 });
2759 };
2760 AnimationTransitionNamespace.prototype.triggerLeaveAnimation = function (element, context, destroyAfterComplete, defaultToFallback) {
2761 var _this = this;
2762 var triggerStates = this._engine.statesByElement.get(element);
2763 if (triggerStates) {
2764 var players_1 = [];
2765 Object.keys(triggerStates).forEach(function (triggerName) {
2766 // this check is here in the event that an element is removed
2767 // twice (both on the host level and the component level)
2768 if (_this._triggers[triggerName]) {
2769 var player = _this.trigger(element, triggerName, VOID_VALUE, defaultToFallback);
2770 if (player) {
2771 players_1.push(player);
2772 }
2773 }
2774 });
2775 if (players_1.length) {
2776 this._engine.markElementAsRemoved(this.id, element, true, context);
2777 if (destroyAfterComplete) {
2778 optimizeGroupPlayer(players_1).onDone(function () { return _this._engine.processLeaveNode(element); });
2779 }
2780 return true;
2781 }
2782 }
2783 return false;
2784 };
2785 AnimationTransitionNamespace.prototype.prepareLeaveAnimationListeners = function (element) {
2786 var _this = this;
2787 var listeners = this._elementListeners.get(element);
2788 if (listeners) {
2789 var visitedTriggers_1 = new Set();
2790 listeners.forEach(function (listener) {
2791 var triggerName = listener.name;
2792 if (visitedTriggers_1.has(triggerName))
2793 return;
2794 visitedTriggers_1.add(triggerName);
2795 var trigger = _this._triggers[triggerName];
2796 var transition = trigger.fallbackTransition;
2797 var elementStates = _this._engine.statesByElement.get(element);
2798 var fromState = elementStates[triggerName] || DEFAULT_STATE_VALUE;
2799 var toState = new StateValue(VOID_VALUE);
2800 var player = new TransitionAnimationPlayer(_this.id, triggerName, element);
2801 _this._engine.totalQueuedPlayers++;
2802 _this._queue.push({
2803 element: element,
2804 triggerName: triggerName,
2805 transition: transition,
2806 fromState: fromState,
2807 toState: toState,
2808 player: player,
2809 isFallbackTransition: true
2810 });
2811 });
2812 }
2813 };
2814 AnimationTransitionNamespace.prototype.removeNode = function (element, context) {
2815 var _this = this;
2816 var engine = this._engine;
2817 if (element.childElementCount) {
2818 this._signalRemovalForInnerTriggers(element, context, true);
2819 }
2820 // this means that a * => VOID animation was detected and kicked off
2821 if (this.triggerLeaveAnimation(element, context, true))
2822 return;
2823 // find the player that is animating and make sure that the
2824 // removal is delayed until that player has completed
2825 var containsPotentialParentTransition = false;
2826 if (engine.totalAnimations) {
2827 var currentPlayers = engine.players.length ? engine.playersByQueriedElement.get(element) : [];
2828 // when this `if statement` does not continue forward it means that
2829 // a previous animation query has selected the current element and
2830 // is animating it. In this situation want to continue forwards and
2831 // allow the element to be queued up for animation later.
2832 if (currentPlayers && currentPlayers.length) {
2833 containsPotentialParentTransition = true;
2834 }
2835 else {
2836 var parent_1 = element;
2837 while (parent_1 = parent_1.parentNode) {
2838 var triggers = engine.statesByElement.get(parent_1);
2839 if (triggers) {
2840 containsPotentialParentTransition = true;
2841 break;
2842 }
2843 }
2844 }
2845 }
2846 // at this stage we know that the element will either get removed
2847 // during flush or will be picked up by a parent query. Either way
2848 // we need to fire the listeners for this element when it DOES get
2849 // removed (once the query parent animation is done or after flush)
2850 this.prepareLeaveAnimationListeners(element);
2851 // whether or not a parent has an animation we need to delay the deferral of the leave
2852 // operation until we have more information (which we do after flush() has been called)
2853 if (containsPotentialParentTransition) {
2854 engine.markElementAsRemoved(this.id, element, false, context);
2855 }
2856 else {
2857 // we do this after the flush has occurred such
2858 // that the callbacks can be fired
2859 engine.afterFlush(function () { return _this.clearElementCache(element); });
2860 engine.destroyInnerAnimations(element);
2861 engine._onRemovalComplete(element, context);
2862 }
2863 };
2864 AnimationTransitionNamespace.prototype.insertNode = function (element, parent) { addClass(element, this._hostClassName); };
2865 AnimationTransitionNamespace.prototype.drainQueuedTransitions = function (microtaskId) {
2866 var _this = this;
2867 var instructions = [];
2868 this._queue.forEach(function (entry) {
2869 var player = entry.player;
2870 if (player.destroyed)
2871 return;
2872 var element = entry.element;
2873 var listeners = _this._elementListeners.get(element);
2874 if (listeners) {
2875 listeners.forEach(function (listener) {
2876 if (listener.name == entry.triggerName) {
2877 var baseEvent = makeAnimationEvent(element, entry.triggerName, entry.fromState.value, entry.toState.value);
2878 baseEvent['_data'] = microtaskId;
2879 listenOnPlayer(entry.player, listener.phase, baseEvent, listener.callback);
2880 }
2881 });
2882 }
2883 if (player.markedForDestroy) {
2884 _this._engine.afterFlush(function () {
2885 // now we can destroy the element properly since the event listeners have
2886 // been bound to the player
2887 player.destroy();
2888 });
2889 }
2890 else {
2891 instructions.push(entry);
2892 }
2893 });
2894 this._queue = [];
2895 return instructions.sort(function (a, b) {
2896 // if depCount == 0 them move to front
2897 // otherwise if a contains b then move back
2898 var d0 = a.transition.ast.depCount;
2899 var d1 = b.transition.ast.depCount;
2900 if (d0 == 0 || d1 == 0) {
2901 return d0 - d1;
2902 }
2903 return _this._engine.driver.containsElement(a.element, b.element) ? 1 : -1;
2904 });
2905 };
2906 AnimationTransitionNamespace.prototype.destroy = function (context) {
2907 this.players.forEach(function (p) { return p.destroy(); });
2908 this._signalRemovalForInnerTriggers(this.hostElement, context);
2909 };
2910 AnimationTransitionNamespace.prototype.elementContainsData = function (element) {
2911 var containsData = false;
2912 if (this._elementListeners.has(element))
2913 containsData = true;
2914 containsData =
2915 (this._queue.find(function (entry) { return entry.element === element; }) ? true : false) || containsData;
2916 return containsData;
2917 };
2918 return AnimationTransitionNamespace;
2919 }());
2920 var TransitionAnimationEngine = /** @class */ (function () {
2921 function TransitionAnimationEngine(bodyNode, driver, _normalizer) {
2922 this.bodyNode = bodyNode;
2923 this.driver = driver;
2924 this._normalizer = _normalizer;
2925 this.players = [];
2926 this.newHostElements = new Map();
2927 this.playersByElement = new Map();
2928 this.playersByQueriedElement = new Map();
2929 this.statesByElement = new Map();
2930 this.disabledNodes = new Set();
2931 this.totalAnimations = 0;
2932 this.totalQueuedPlayers = 0;
2933 this._namespaceLookup = {};
2934 this._namespaceList = [];
2935 this._flushFns = [];
2936 this._whenQuietFns = [];
2937 this.namespacesByHostElement = new Map();
2938 this.collectedEnterElements = [];
2939 this.collectedLeaveElements = [];
2940 // this method is designed to be overridden by the code that uses this engine
2941 this.onRemovalComplete = function (element, context) { };
2942 }
2943 /** @internal */
2944 TransitionAnimationEngine.prototype._onRemovalComplete = function (element, context) { this.onRemovalComplete(element, context); };
2945 Object.defineProperty(TransitionAnimationEngine.prototype, "queuedPlayers", {
2946 get: function () {
2947 var players = [];
2948 this._namespaceList.forEach(function (ns) {
2949 ns.players.forEach(function (player) {
2950 if (player.queued) {
2951 players.push(player);
2952 }
2953 });
2954 });
2955 return players;
2956 },
2957 enumerable: true,
2958 configurable: true
2959 });
2960 TransitionAnimationEngine.prototype.createNamespace = function (namespaceId, hostElement) {
2961 var ns = new AnimationTransitionNamespace(namespaceId, hostElement, this);
2962 if (hostElement.parentNode) {
2963 this._balanceNamespaceList(ns, hostElement);
2964 }
2965 else {
2966 // defer this later until flush during when the host element has
2967 // been inserted so that we know exactly where to place it in
2968 // the namespace list
2969 this.newHostElements.set(hostElement, ns);
2970 // given that this host element is apart of the animation code, it
2971 // may or may not be inserted by a parent node that is an of an
2972 // animation renderer type. If this happens then we can still have
2973 // access to this item when we query for :enter nodes. If the parent
2974 // is a renderer then the set data-structure will normalize the entry
2975 this.collectEnterElement(hostElement);
2976 }
2977 return this._namespaceLookup[namespaceId] = ns;
2978 };
2979 TransitionAnimationEngine.prototype._balanceNamespaceList = function (ns, hostElement) {
2980 var limit = this._namespaceList.length - 1;
2981 if (limit >= 0) {
2982 var found = false;
2983 for (var i = limit; i >= 0; i--) {
2984 var nextNamespace = this._namespaceList[i];
2985 if (this.driver.containsElement(nextNamespace.hostElement, hostElement)) {
2986 this._namespaceList.splice(i + 1, 0, ns);
2987 found = true;
2988 break;
2989 }
2990 }
2991 if (!found) {
2992 this._namespaceList.splice(0, 0, ns);
2993 }
2994 }
2995 else {
2996 this._namespaceList.push(ns);
2997 }
2998 this.namespacesByHostElement.set(hostElement, ns);
2999 return ns;
3000 };
3001 TransitionAnimationEngine.prototype.register = function (namespaceId, hostElement) {
3002 var ns = this._namespaceLookup[namespaceId];
3003 if (!ns) {
3004 ns = this.createNamespace(namespaceId, hostElement);
3005 }
3006 return ns;
3007 };
3008 TransitionAnimationEngine.prototype.registerTrigger = function (namespaceId, name, trigger) {
3009 var ns = this._namespaceLookup[namespaceId];
3010 if (ns && ns.register(name, trigger)) {
3011 this.totalAnimations++;
3012 }
3013 };
3014 TransitionAnimationEngine.prototype.destroy = function (namespaceId, context) {
3015 var _this = this;
3016 if (!namespaceId)
3017 return;
3018 var ns = this._fetchNamespace(namespaceId);
3019 this.afterFlush(function () {
3020 _this.namespacesByHostElement.delete(ns.hostElement);
3021 delete _this._namespaceLookup[namespaceId];
3022 var index = _this._namespaceList.indexOf(ns);
3023 if (index >= 0) {
3024 _this._namespaceList.splice(index, 1);
3025 }
3026 });
3027 this.afterFlushAnimationsDone(function () { return ns.destroy(context); });
3028 };
3029 TransitionAnimationEngine.prototype._fetchNamespace = function (id) { return this._namespaceLookup[id]; };
3030 TransitionAnimationEngine.prototype.fetchNamespacesByElement = function (element) {
3031 // normally there should only be one namespace per element, however
3032 // if @triggers are placed on both the component element and then
3033 // its host element (within the component code) then there will be
3034 // two namespaces returned. We use a set here to simply the dedupe
3035 // of namespaces incase there are multiple triggers both the elm and host
3036 var namespaces = new Set();
3037 var elementStates = this.statesByElement.get(element);
3038 if (elementStates) {
3039 var keys = Object.keys(elementStates);
3040 for (var i = 0; i < keys.length; i++) {
3041 var nsId = elementStates[keys[i]].namespaceId;
3042 if (nsId) {
3043 var ns = this._fetchNamespace(nsId);
3044 if (ns) {
3045 namespaces.add(ns);
3046 }
3047 }
3048 }
3049 }
3050 return namespaces;
3051 };
3052 TransitionAnimationEngine.prototype.trigger = function (namespaceId, element, name, value) {
3053 if (isElementNode(element)) {
3054 var ns = this._fetchNamespace(namespaceId);
3055 if (ns) {
3056 ns.trigger(element, name, value);
3057 return true;
3058 }
3059 }
3060 return false;
3061 };
3062 TransitionAnimationEngine.prototype.insertNode = function (namespaceId, element, parent, insertBefore) {
3063 if (!isElementNode(element))
3064 return;
3065 // special case for when an element is removed and reinserted (move operation)
3066 // when this occurs we do not want to use the element for deletion later
3067 var details = element[REMOVAL_FLAG];
3068 if (details && details.setForRemoval) {
3069 details.setForRemoval = false;
3070 details.setForMove = true;
3071 var index = this.collectedLeaveElements.indexOf(element);
3072 if (index >= 0) {
3073 this.collectedLeaveElements.splice(index, 1);
3074 }
3075 }
3076 // in the event that the namespaceId is blank then the caller
3077 // code does not contain any animation code in it, but it is
3078 // just being called so that the node is marked as being inserted
3079 if (namespaceId) {
3080 var ns = this._fetchNamespace(namespaceId);
3081 // This if-statement is a workaround for router issue #21947.
3082 // The router sometimes hits a race condition where while a route
3083 // is being instantiated a new navigation arrives, triggering leave
3084 // animation of DOM that has not been fully initialized, until this
3085 // is resolved, we need to handle the scenario when DOM is not in a
3086 // consistent state during the animation.
3087 if (ns) {
3088 ns.insertNode(element, parent);
3089 }
3090 }
3091 // only *directives and host elements are inserted before
3092 if (insertBefore) {
3093 this.collectEnterElement(element);
3094 }
3095 };
3096 TransitionAnimationEngine.prototype.collectEnterElement = function (element) { this.collectedEnterElements.push(element); };
3097 TransitionAnimationEngine.prototype.markElementAsDisabled = function (element, value) {
3098 if (value) {
3099 if (!this.disabledNodes.has(element)) {
3100 this.disabledNodes.add(element);
3101 addClass(element, DISABLED_CLASSNAME);
3102 }
3103 }
3104 else if (this.disabledNodes.has(element)) {
3105 this.disabledNodes.delete(element);
3106 removeClass(element, DISABLED_CLASSNAME);
3107 }
3108 };
3109 TransitionAnimationEngine.prototype.removeNode = function (namespaceId, element, isHostElement, context) {
3110 if (isElementNode(element)) {
3111 var ns = namespaceId ? this._fetchNamespace(namespaceId) : null;
3112 if (ns) {
3113 ns.removeNode(element, context);
3114 }
3115 else {
3116 this.markElementAsRemoved(namespaceId, element, false, context);
3117 }
3118 if (isHostElement) {
3119 var hostNS = this.namespacesByHostElement.get(element);
3120 if (hostNS && hostNS.id !== namespaceId) {
3121 hostNS.removeNode(element, context);
3122 }
3123 }
3124 }
3125 else {
3126 this._onRemovalComplete(element, context);
3127 }
3128 };
3129 TransitionAnimationEngine.prototype.markElementAsRemoved = function (namespaceId, element, hasAnimation, context) {
3130 this.collectedLeaveElements.push(element);
3131 element[REMOVAL_FLAG] = {
3132 namespaceId: namespaceId,
3133 setForRemoval: context, hasAnimation: hasAnimation,
3134 removedBeforeQueried: false
3135 };
3136 };
3137 TransitionAnimationEngine.prototype.listen = function (namespaceId, element, name, phase, callback) {
3138 if (isElementNode(element)) {
3139 return this._fetchNamespace(namespaceId).listen(element, name, phase, callback);
3140 }
3141 return function () { };
3142 };
3143 TransitionAnimationEngine.prototype._buildInstruction = function (entry, subTimelines, enterClassName, leaveClassName, skipBuildAst) {
3144 return entry.transition.build(this.driver, entry.element, entry.fromState.value, entry.toState.value, enterClassName, leaveClassName, entry.fromState.options, entry.toState.options, subTimelines, skipBuildAst);
3145 };
3146 TransitionAnimationEngine.prototype.destroyInnerAnimations = function (containerElement) {
3147 var _this = this;
3148 var elements = this.driver.query(containerElement, NG_TRIGGER_SELECTOR, true);
3149 elements.forEach(function (element) { return _this.destroyActiveAnimationsForElement(element); });
3150 if (this.playersByQueriedElement.size == 0)
3151 return;
3152 elements = this.driver.query(containerElement, NG_ANIMATING_SELECTOR, true);
3153 elements.forEach(function (element) { return _this.finishActiveQueriedAnimationOnElement(element); });
3154 };
3155 TransitionAnimationEngine.prototype.destroyActiveAnimationsForElement = function (element) {
3156 var players = this.playersByElement.get(element);
3157 if (players) {
3158 players.forEach(function (player) {
3159 // special case for when an element is set for destruction, but hasn't started.
3160 // in this situation we want to delay the destruction until the flush occurs
3161 // so that any event listeners attached to the player are triggered.
3162 if (player.queued) {
3163 player.markedForDestroy = true;
3164 }
3165 else {
3166 player.destroy();
3167 }
3168 });
3169 }
3170 };
3171 TransitionAnimationEngine.prototype.finishActiveQueriedAnimationOnElement = function (element) {
3172 var players = this.playersByQueriedElement.get(element);
3173 if (players) {
3174 players.forEach(function (player) { return player.finish(); });
3175 }
3176 };
3177 TransitionAnimationEngine.prototype.whenRenderingDone = function () {
3178 var _this = this;
3179 return new Promise(function (resolve) {
3180 if (_this.players.length) {
3181 return optimizeGroupPlayer(_this.players).onDone(function () { return resolve(); });
3182 }
3183 else {
3184 resolve();
3185 }
3186 });
3187 };
3188 TransitionAnimationEngine.prototype.processLeaveNode = function (element) {
3189 var _this = this;
3190 var details = element[REMOVAL_FLAG];
3191 if (details && details.setForRemoval) {
3192 // this will prevent it from removing it twice
3193 element[REMOVAL_FLAG] = NULL_REMOVAL_STATE;
3194 if (details.namespaceId) {
3195 this.destroyInnerAnimations(element);
3196 var ns = this._fetchNamespace(details.namespaceId);
3197 if (ns) {
3198 ns.clearElementCache(element);
3199 }
3200 }
3201 this._onRemovalComplete(element, details.setForRemoval);
3202 }
3203 if (this.driver.matchesElement(element, DISABLED_SELECTOR)) {
3204 this.markElementAsDisabled(element, false);
3205 }
3206 this.driver.query(element, DISABLED_SELECTOR, true).forEach(function (node) {
3207 _this.markElementAsDisabled(node, false);
3208 });
3209 };
3210 TransitionAnimationEngine.prototype.flush = function (microtaskId) {
3211 var _this = this;
3212 if (microtaskId === void 0) { microtaskId = -1; }
3213 var players = [];
3214 if (this.newHostElements.size) {
3215 this.newHostElements.forEach(function (ns, element) { return _this._balanceNamespaceList(ns, element); });
3216 this.newHostElements.clear();
3217 }
3218 if (this.totalAnimations && this.collectedEnterElements.length) {
3219 for (var i = 0; i < this.collectedEnterElements.length; i++) {
3220 var elm = this.collectedEnterElements[i];
3221 addClass(elm, STAR_CLASSNAME);
3222 }
3223 }
3224 if (this._namespaceList.length &&
3225 (this.totalQueuedPlayers || this.collectedLeaveElements.length)) {
3226 var cleanupFns = [];
3227 try {
3228 players = this._flushAnimations(cleanupFns, microtaskId);
3229 }
3230 finally {
3231 for (var i = 0; i < cleanupFns.length; i++) {
3232 cleanupFns[i]();
3233 }
3234 }
3235 }
3236 else {
3237 for (var i = 0; i < this.collectedLeaveElements.length; i++) {
3238 var element = this.collectedLeaveElements[i];
3239 this.processLeaveNode(element);
3240 }
3241 }
3242 this.totalQueuedPlayers = 0;
3243 this.collectedEnterElements.length = 0;
3244 this.collectedLeaveElements.length = 0;
3245 this._flushFns.forEach(function (fn) { return fn(); });
3246 this._flushFns = [];
3247 if (this._whenQuietFns.length) {
3248 // we move these over to a variable so that
3249 // if any new callbacks are registered in another
3250 // flush they do not populate the existing set
3251 var quietFns_1 = this._whenQuietFns;
3252 this._whenQuietFns = [];
3253 if (players.length) {
3254 optimizeGroupPlayer(players).onDone(function () { quietFns_1.forEach(function (fn) { return fn(); }); });
3255 }
3256 else {
3257 quietFns_1.forEach(function (fn) { return fn(); });
3258 }
3259 }
3260 };
3261 TransitionAnimationEngine.prototype.reportError = function (errors) {
3262 throw new Error("Unable to process animations due to the following failed trigger transitions\n " + errors.join('\n'));
3263 };
3264 TransitionAnimationEngine.prototype._flushAnimations = function (cleanupFns, microtaskId) {
3265 var _this = this;
3266 var subTimelines = new ElementInstructionMap();
3267 var skippedPlayers = [];
3268 var skippedPlayersMap = new Map();
3269 var queuedInstructions = [];
3270 var queriedElements = new Map();
3271 var allPreStyleElements = new Map();
3272 var allPostStyleElements = new Map();
3273 var disabledElementsSet = new Set();
3274 this.disabledNodes.forEach(function (node) {
3275 disabledElementsSet.add(node);
3276 var nodesThatAreDisabled = _this.driver.query(node, QUEUED_SELECTOR, true);
3277 for (var i_1 = 0; i_1 < nodesThatAreDisabled.length; i_1++) {
3278 disabledElementsSet.add(nodesThatAreDisabled[i_1]);
3279 }
3280 });
3281 var bodyNode = this.bodyNode;
3282 var allTriggerElements = Array.from(this.statesByElement.keys());
3283 var enterNodeMap = buildRootMap(allTriggerElements, this.collectedEnterElements);
3284 // this must occur before the instructions are built below such that
3285 // the :enter queries match the elements (since the timeline queries
3286 // are fired during instruction building).
3287 var enterNodeMapIds = new Map();
3288 var i = 0;
3289 enterNodeMap.forEach(function (nodes, root) {
3290 var className = ENTER_CLASSNAME + i++;
3291 enterNodeMapIds.set(root, className);
3292 nodes.forEach(function (node) { return addClass(node, className); });
3293 });
3294 var allLeaveNodes = [];
3295 var mergedLeaveNodes = new Set();
3296 var leaveNodesWithoutAnimations = new Set();
3297 for (var i_2 = 0; i_2 < this.collectedLeaveElements.length; i_2++) {
3298 var element = this.collectedLeaveElements[i_2];
3299 var details = element[REMOVAL_FLAG];
3300 if (details && details.setForRemoval) {
3301 allLeaveNodes.push(element);
3302 mergedLeaveNodes.add(element);
3303 if (details.hasAnimation) {
3304 this.driver.query(element, STAR_SELECTOR, true).forEach(function (elm) { return mergedLeaveNodes.add(elm); });
3305 }
3306 else {
3307 leaveNodesWithoutAnimations.add(element);
3308 }
3309 }
3310 }
3311 var leaveNodeMapIds = new Map();
3312 var leaveNodeMap = buildRootMap(allTriggerElements, Array.from(mergedLeaveNodes));
3313 leaveNodeMap.forEach(function (nodes, root) {
3314 var className = LEAVE_CLASSNAME + i++;
3315 leaveNodeMapIds.set(root, className);
3316 nodes.forEach(function (node) { return addClass(node, className); });
3317 });
3318 cleanupFns.push(function () {
3319 enterNodeMap.forEach(function (nodes, root) {
3320 var className = enterNodeMapIds.get(root);
3321 nodes.forEach(function (node) { return removeClass(node, className); });
3322 });
3323 leaveNodeMap.forEach(function (nodes, root) {
3324 var className = leaveNodeMapIds.get(root);
3325 nodes.forEach(function (node) { return removeClass(node, className); });
3326 });
3327 allLeaveNodes.forEach(function (element) { _this.processLeaveNode(element); });
3328 });
3329 var allPlayers = [];
3330 var erroneousTransitions = [];
3331 for (var i_3 = this._namespaceList.length - 1; i_3 >= 0; i_3--) {
3332 var ns = this._namespaceList[i_3];
3333 ns.drainQueuedTransitions(microtaskId).forEach(function (entry) {
3334 var player = entry.player;
3335 var element = entry.element;
3336 allPlayers.push(player);
3337 if (_this.collectedEnterElements.length) {
3338 var details = element[REMOVAL_FLAG];
3339 // move animations are currently not supported...
3340 if (details && details.setForMove) {
3341 player.destroy();
3342 return;
3343 }
3344 }
3345 var nodeIsOrphaned = !bodyNode || !_this.driver.containsElement(bodyNode, element);
3346 var leaveClassName = leaveNodeMapIds.get(element);
3347 var enterClassName = enterNodeMapIds.get(element);
3348 var instruction = _this._buildInstruction(entry, subTimelines, enterClassName, leaveClassName, nodeIsOrphaned);
3349 if (instruction.errors && instruction.errors.length) {
3350 erroneousTransitions.push(instruction);
3351 return;
3352 }
3353 // even though the element may not be apart of the DOM, it may
3354 // still be added at a later point (due to the mechanics of content
3355 // projection and/or dynamic component insertion) therefore it's
3356 // important we still style the element.
3357 if (nodeIsOrphaned) {
3358 player.onStart(function () { return eraseStyles(element, instruction.fromStyles); });
3359 player.onDestroy(function () { return setStyles(element, instruction.toStyles); });
3360 skippedPlayers.push(player);
3361 return;
3362 }
3363 // if a unmatched transition is queued to go then it SHOULD NOT render
3364 // an animation and cancel the previously running animations.
3365 if (entry.isFallbackTransition) {
3366 player.onStart(function () { return eraseStyles(element, instruction.fromStyles); });
3367 player.onDestroy(function () { return setStyles(element, instruction.toStyles); });
3368 skippedPlayers.push(player);
3369 return;
3370 }
3371 // this means that if a parent animation uses this animation as a sub trigger
3372 // then it will instruct the timeline builder to not add a player delay, but
3373 // instead stretch the first keyframe gap up until the animation starts. The
3374 // reason this is important is to prevent extra initialization styles from being
3375 // required by the user in the animation.
3376 instruction.timelines.forEach(function (tl) { return tl.stretchStartingKeyframe = true; });
3377 subTimelines.append(element, instruction.timelines);
3378 var tuple = { instruction: instruction, player: player, element: element };
3379 queuedInstructions.push(tuple);
3380 instruction.queriedElements.forEach(function (element) { return getOrSetAsInMap(queriedElements, element, []).push(player); });
3381 instruction.preStyleProps.forEach(function (stringMap, element) {
3382 var props = Object.keys(stringMap);
3383 if (props.length) {
3384 var setVal_1 = allPreStyleElements.get(element);
3385 if (!setVal_1) {
3386 allPreStyleElements.set(element, setVal_1 = new Set());
3387 }
3388 props.forEach(function (prop) { return setVal_1.add(prop); });
3389 }
3390 });
3391 instruction.postStyleProps.forEach(function (stringMap, element) {
3392 var props = Object.keys(stringMap);
3393 var setVal = allPostStyleElements.get(element);
3394 if (!setVal) {
3395 allPostStyleElements.set(element, setVal = new Set());
3396 }
3397 props.forEach(function (prop) { return setVal.add(prop); });
3398 });
3399 });
3400 }
3401 if (erroneousTransitions.length) {
3402 var errors_1 = [];
3403 erroneousTransitions.forEach(function (instruction) {
3404 errors_1.push("@" + instruction.triggerName + " has failed due to:\n");
3405 instruction.errors.forEach(function (error) { return errors_1.push("- " + error + "\n"); });
3406 });
3407 allPlayers.forEach(function (player) { return player.destroy(); });
3408 this.reportError(errors_1);
3409 }
3410 var allPreviousPlayersMap = new Map();
3411 // this map works to tell which element in the DOM tree is contained by
3412 // which animation. Further down below this map will get populated once
3413 // the players are built and in doing so it can efficiently figure out
3414 // if a sub player is skipped due to a parent player having priority.
3415 var animationElementMap = new Map();
3416 queuedInstructions.forEach(function (entry) {
3417 var element = entry.element;
3418 if (subTimelines.has(element)) {
3419 animationElementMap.set(element, element);
3420 _this._beforeAnimationBuild(entry.player.namespaceId, entry.instruction, allPreviousPlayersMap);
3421 }
3422 });
3423 skippedPlayers.forEach(function (player) {
3424 var element = player.element;
3425 var previousPlayers = _this._getPreviousPlayers(element, false, player.namespaceId, player.triggerName, null);
3426 previousPlayers.forEach(function (prevPlayer) {
3427 getOrSetAsInMap(allPreviousPlayersMap, element, []).push(prevPlayer);
3428 prevPlayer.destroy();
3429 });
3430 });
3431 // this is a special case for nodes that will be removed (either by)
3432 // having their own leave animations or by being queried in a container
3433 // that will be removed once a parent animation is complete. The idea
3434 // here is that * styles must be identical to ! styles because of
3435 // backwards compatibility (* is also filled in by default in many places).
3436 // Otherwise * styles will return an empty value or auto since the element
3437 // that is being getComputedStyle'd will not be visible (since * = destination)
3438 var replaceNodes = allLeaveNodes.filter(function (node) {
3439 return replacePostStylesAsPre(node, allPreStyleElements, allPostStyleElements);
3440 });
3441 // POST STAGE: fill the * styles
3442 var postStylesMap = new Map();
3443 var allLeaveQueriedNodes = cloakAndComputeStyles(postStylesMap, this.driver, leaveNodesWithoutAnimations, allPostStyleElements, animations.AUTO_STYLE);
3444 allLeaveQueriedNodes.forEach(function (node) {
3445 if (replacePostStylesAsPre(node, allPreStyleElements, allPostStyleElements)) {
3446 replaceNodes.push(node);
3447 }
3448 });
3449 // PRE STAGE: fill the ! styles
3450 var preStylesMap = new Map();
3451 enterNodeMap.forEach(function (nodes, root) {
3452 cloakAndComputeStyles(preStylesMap, _this.driver, new Set(nodes), allPreStyleElements, animations.ɵPRE_STYLE);
3453 });
3454 replaceNodes.forEach(function (node) {
3455 var post = postStylesMap.get(node);
3456 var pre = preStylesMap.get(node);
3457 postStylesMap.set(node, __assign({}, post, pre));
3458 });
3459 var rootPlayers = [];
3460 var subPlayers = [];
3461 var NO_PARENT_ANIMATION_ELEMENT_DETECTED = {};
3462 queuedInstructions.forEach(function (entry) {
3463 var element = entry.element, player = entry.player, instruction = entry.instruction;
3464 // this means that it was never consumed by a parent animation which
3465 // means that it is independent and therefore should be set for animation
3466 if (subTimelines.has(element)) {
3467 if (disabledElementsSet.has(element)) {
3468 player.onDestroy(function () { return setStyles(element, instruction.toStyles); });
3469 player.disabled = true;
3470 player.overrideTotalTime(instruction.totalTime);
3471 skippedPlayers.push(player);
3472 return;
3473 }
3474 // this will flow up the DOM and query the map to figure out
3475 // if a parent animation has priority over it. In the situation
3476 // that a parent is detected then it will cancel the loop. If
3477 // nothing is detected, or it takes a few hops to find a parent,
3478 // then it will fill in the missing nodes and signal them as having
3479 // a detected parent (or a NO_PARENT value via a special constant).
3480 var parentWithAnimation_1 = NO_PARENT_ANIMATION_ELEMENT_DETECTED;
3481 if (animationElementMap.size > 1) {
3482 var elm = element;
3483 var parentsToAdd = [];
3484 while (elm = elm.parentNode) {
3485 var detectedParent = animationElementMap.get(elm);
3486 if (detectedParent) {
3487 parentWithAnimation_1 = detectedParent;
3488 break;
3489 }
3490 parentsToAdd.push(elm);
3491 }
3492 parentsToAdd.forEach(function (parent) { return animationElementMap.set(parent, parentWithAnimation_1); });
3493 }
3494 var innerPlayer = _this._buildAnimation(player.namespaceId, instruction, allPreviousPlayersMap, skippedPlayersMap, preStylesMap, postStylesMap);
3495 player.setRealPlayer(innerPlayer);
3496 if (parentWithAnimation_1 === NO_PARENT_ANIMATION_ELEMENT_DETECTED) {
3497 rootPlayers.push(player);
3498 }
3499 else {
3500 var parentPlayers = _this.playersByElement.get(parentWithAnimation_1);
3501 if (parentPlayers && parentPlayers.length) {
3502 player.parentPlayer = optimizeGroupPlayer(parentPlayers);
3503 }
3504 skippedPlayers.push(player);
3505 }
3506 }
3507 else {
3508 eraseStyles(element, instruction.fromStyles);
3509 player.onDestroy(function () { return setStyles(element, instruction.toStyles); });
3510 // there still might be a ancestor player animating this
3511 // element therefore we will still add it as a sub player
3512 // even if its animation may be disabled
3513 subPlayers.push(player);
3514 if (disabledElementsSet.has(element)) {
3515 skippedPlayers.push(player);
3516 }
3517 }
3518 });
3519 // find all of the sub players' corresponding inner animation player
3520 subPlayers.forEach(function (player) {
3521 // even if any players are not found for a sub animation then it
3522 // will still complete itself after the next tick since it's Noop
3523 var playersForElement = skippedPlayersMap.get(player.element);
3524 if (playersForElement && playersForElement.length) {
3525 var innerPlayer = optimizeGroupPlayer(playersForElement);
3526 player.setRealPlayer(innerPlayer);
3527 }
3528 });
3529 // the reason why we don't actually play the animation is
3530 // because all that a skipped player is designed to do is to
3531 // fire the start/done transition callback events
3532 skippedPlayers.forEach(function (player) {
3533 if (player.parentPlayer) {
3534 player.syncPlayerEvents(player.parentPlayer);
3535 }
3536 else {
3537 player.destroy();
3538 }
3539 });
3540 // run through all of the queued removals and see if they
3541 // were picked up by a query. If not then perform the removal
3542 // operation right away unless a parent animation is ongoing.
3543 for (var i_4 = 0; i_4 < allLeaveNodes.length; i_4++) {
3544 var element = allLeaveNodes[i_4];
3545 var details = element[REMOVAL_FLAG];
3546 removeClass(element, LEAVE_CLASSNAME);
3547 // this means the element has a removal animation that is being
3548 // taken care of and therefore the inner elements will hang around
3549 // until that animation is over (or the parent queried animation)
3550 if (details && details.hasAnimation)
3551 continue;
3552 var players = [];
3553 // if this element is queried or if it contains queried children
3554 // then we want for the element not to be removed from the page
3555 // until the queried animations have finished
3556 if (queriedElements.size) {
3557 var queriedPlayerResults = queriedElements.get(element);
3558 if (queriedPlayerResults && queriedPlayerResults.length) {
3559 players.push.apply(players, __spread(queriedPlayerResults));
3560 }
3561 var queriedInnerElements = this.driver.query(element, NG_ANIMATING_SELECTOR, true);
3562 for (var j = 0; j < queriedInnerElements.length; j++) {
3563 var queriedPlayers = queriedElements.get(queriedInnerElements[j]);
3564 if (queriedPlayers && queriedPlayers.length) {
3565 players.push.apply(players, __spread(queriedPlayers));
3566 }
3567 }
3568 }
3569 var activePlayers = players.filter(function (p) { return !p.destroyed; });
3570 if (activePlayers.length) {
3571 removeNodesAfterAnimationDone(this, element, activePlayers);
3572 }
3573 else {
3574 this.processLeaveNode(element);
3575 }
3576 }
3577 // this is required so the cleanup method doesn't remove them
3578 allLeaveNodes.length = 0;
3579 rootPlayers.forEach(function (player) {
3580 _this.players.push(player);
3581 player.onDone(function () {
3582 player.destroy();
3583 var index = _this.players.indexOf(player);
3584 _this.players.splice(index, 1);
3585 });
3586 player.play();
3587 });
3588 return rootPlayers;
3589 };
3590 TransitionAnimationEngine.prototype.elementContainsData = function (namespaceId, element) {
3591 var containsData = false;
3592 var details = element[REMOVAL_FLAG];
3593 if (details && details.setForRemoval)
3594 containsData = true;
3595 if (this.playersByElement.has(element))
3596 containsData = true;
3597 if (this.playersByQueriedElement.has(element))
3598 containsData = true;
3599 if (this.statesByElement.has(element))
3600 containsData = true;
3601 return this._fetchNamespace(namespaceId).elementContainsData(element) || containsData;
3602 };
3603 TransitionAnimationEngine.prototype.afterFlush = function (callback) { this._flushFns.push(callback); };
3604 TransitionAnimationEngine.prototype.afterFlushAnimationsDone = function (callback) { this._whenQuietFns.push(callback); };
3605 TransitionAnimationEngine.prototype._getPreviousPlayers = function (element, isQueriedElement, namespaceId, triggerName, toStateValue) {
3606 var players = [];
3607 if (isQueriedElement) {
3608 var queriedElementPlayers = this.playersByQueriedElement.get(element);
3609 if (queriedElementPlayers) {
3610 players = queriedElementPlayers;
3611 }
3612 }
3613 else {
3614 var elementPlayers = this.playersByElement.get(element);
3615 if (elementPlayers) {
3616 var isRemovalAnimation_1 = !toStateValue || toStateValue == VOID_VALUE;
3617 elementPlayers.forEach(function (player) {
3618 if (player.queued)
3619 return;
3620 if (!isRemovalAnimation_1 && player.triggerName != triggerName)
3621 return;
3622 players.push(player);
3623 });
3624 }
3625 }
3626 if (namespaceId || triggerName) {
3627 players = players.filter(function (player) {
3628 if (namespaceId && namespaceId != player.namespaceId)
3629 return false;
3630 if (triggerName && triggerName != player.triggerName)
3631 return false;
3632 return true;
3633 });
3634 }
3635 return players;
3636 };
3637 TransitionAnimationEngine.prototype._beforeAnimationBuild = function (namespaceId, instruction, allPreviousPlayersMap) {
3638 var e_1, _a;
3639 var triggerName = instruction.triggerName;
3640 var rootElement = instruction.element;
3641 // when a removal animation occurs, ALL previous players are collected
3642 // and destroyed (even if they are outside of the current namespace)
3643 var targetNameSpaceId = instruction.isRemovalTransition ? undefined : namespaceId;
3644 var targetTriggerName = instruction.isRemovalTransition ? undefined : triggerName;
3645 var _loop_1 = function (timelineInstruction) {
3646 var element = timelineInstruction.element;
3647 var isQueriedElement = element !== rootElement;
3648 var players = getOrSetAsInMap(allPreviousPlayersMap, element, []);
3649 var previousPlayers = this_1._getPreviousPlayers(element, isQueriedElement, targetNameSpaceId, targetTriggerName, instruction.toState);
3650 previousPlayers.forEach(function (player) {
3651 var realPlayer = player.getRealPlayer();
3652 if (realPlayer.beforeDestroy) {
3653 realPlayer.beforeDestroy();
3654 }
3655 player.destroy();
3656 players.push(player);
3657 });
3658 };
3659 var this_1 = this;
3660 try {
3661 for (var _b = __values(instruction.timelines), _c = _b.next(); !_c.done; _c = _b.next()) {
3662 var timelineInstruction = _c.value;
3663 _loop_1(timelineInstruction);
3664 }
3665 }
3666 catch (e_1_1) { e_1 = { error: e_1_1 }; }
3667 finally {
3668 try {
3669 if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
3670 }
3671 finally { if (e_1) throw e_1.error; }
3672 }
3673 // this needs to be done so that the PRE/POST styles can be
3674 // computed properly without interfering with the previous animation
3675 eraseStyles(rootElement, instruction.fromStyles);
3676 };
3677 TransitionAnimationEngine.prototype._buildAnimation = function (namespaceId, instruction, allPreviousPlayersMap, skippedPlayersMap, preStylesMap, postStylesMap) {
3678 var _this = this;
3679 var triggerName = instruction.triggerName;
3680 var rootElement = instruction.element;
3681 // we first run this so that the previous animation player
3682 // data can be passed into the successive animation players
3683 var allQueriedPlayers = [];
3684 var allConsumedElements = new Set();
3685 var allSubElements = new Set();
3686 var allNewPlayers = instruction.timelines.map(function (timelineInstruction) {
3687 var element = timelineInstruction.element;
3688 allConsumedElements.add(element);
3689 // FIXME (matsko): make sure to-be-removed animations are removed properly
3690 var details = element[REMOVAL_FLAG];
3691 if (details && details.removedBeforeQueried)
3692 return new animations.NoopAnimationPlayer(timelineInstruction.duration, timelineInstruction.delay);
3693 var isQueriedElement = element !== rootElement;
3694 var previousPlayers = flattenGroupPlayers((allPreviousPlayersMap.get(element) || EMPTY_PLAYER_ARRAY)
3695 .map(function (p) { return p.getRealPlayer(); }))
3696 .filter(function (p) {
3697 // the `element` is not apart of the AnimationPlayer definition, but
3698 // Mock/WebAnimations
3699 // use the element within their implementation. This will be added in Angular5 to
3700 // AnimationPlayer
3701 var pp = p;
3702 return pp.element ? pp.element === element : false;
3703 });
3704 var preStyles = preStylesMap.get(element);
3705 var postStyles = postStylesMap.get(element);
3706 var keyframes = normalizeKeyframes(_this.driver, _this._normalizer, element, timelineInstruction.keyframes, preStyles, postStyles);
3707 var player = _this._buildPlayer(timelineInstruction, keyframes, previousPlayers);
3708 // this means that this particular player belongs to a sub trigger. It is
3709 // important that we match this player up with the corresponding (@trigger.listener)
3710 if (timelineInstruction.subTimeline && skippedPlayersMap) {
3711 allSubElements.add(element);
3712 }
3713 if (isQueriedElement) {
3714 var wrappedPlayer = new TransitionAnimationPlayer(namespaceId, triggerName, element);
3715 wrappedPlayer.setRealPlayer(player);
3716 allQueriedPlayers.push(wrappedPlayer);
3717 }
3718 return player;
3719 });
3720 allQueriedPlayers.forEach(function (player) {
3721 getOrSetAsInMap(_this.playersByQueriedElement, player.element, []).push(player);
3722 player.onDone(function () { return deleteOrUnsetInMap(_this.playersByQueriedElement, player.element, player); });
3723 });
3724 allConsumedElements.forEach(function (element) { return addClass(element, NG_ANIMATING_CLASSNAME); });
3725 var player = optimizeGroupPlayer(allNewPlayers);
3726 player.onDestroy(function () {
3727 allConsumedElements.forEach(function (element) { return removeClass(element, NG_ANIMATING_CLASSNAME); });
3728 setStyles(rootElement, instruction.toStyles);
3729 });
3730 // this basically makes all of the callbacks for sub element animations
3731 // be dependent on the upper players for when they finish
3732 allSubElements.forEach(function (element) { getOrSetAsInMap(skippedPlayersMap, element, []).push(player); });
3733 return player;
3734 };
3735 TransitionAnimationEngine.prototype._buildPlayer = function (instruction, keyframes, previousPlayers) {
3736 if (keyframes.length > 0) {
3737 return this.driver.animate(instruction.element, keyframes, instruction.duration, instruction.delay, instruction.easing, previousPlayers);
3738 }
3739 // special case for when an empty transition|definition is provided
3740 // ... there is no point in rendering an empty animation
3741 return new animations.NoopAnimationPlayer(instruction.duration, instruction.delay);
3742 };
3743 return TransitionAnimationEngine;
3744 }());
3745 var TransitionAnimationPlayer = /** @class */ (function () {
3746 function TransitionAnimationPlayer(namespaceId, triggerName, element) {
3747 this.namespaceId = namespaceId;
3748 this.triggerName = triggerName;
3749 this.element = element;
3750 this._player = new animations.NoopAnimationPlayer();
3751 this._containsRealPlayer = false;
3752 this._queuedCallbacks = {};
3753 this.destroyed = false;
3754 this.markedForDestroy = false;
3755 this.disabled = false;
3756 this.queued = true;
3757 this.totalTime = 0;
3758 }
3759 TransitionAnimationPlayer.prototype.setRealPlayer = function (player) {
3760 var _this = this;
3761 if (this._containsRealPlayer)
3762 return;
3763 this._player = player;
3764 Object.keys(this._queuedCallbacks).forEach(function (phase) {
3765 _this._queuedCallbacks[phase].forEach(function (callback) { return listenOnPlayer(player, phase, undefined, callback); });
3766 });
3767 this._queuedCallbacks = {};
3768 this._containsRealPlayer = true;
3769 this.overrideTotalTime(player.totalTime);
3770 this.queued = false;
3771 };
3772 TransitionAnimationPlayer.prototype.getRealPlayer = function () { return this._player; };
3773 TransitionAnimationPlayer.prototype.overrideTotalTime = function (totalTime) { this.totalTime = totalTime; };
3774 TransitionAnimationPlayer.prototype.syncPlayerEvents = function (player) {
3775 var _this = this;
3776 var p = this._player;
3777 if (p.triggerCallback) {
3778 player.onStart(function () { return p.triggerCallback('start'); });
3779 }
3780 player.onDone(function () { return _this.finish(); });
3781 player.onDestroy(function () { return _this.destroy(); });
3782 };
3783 TransitionAnimationPlayer.prototype._queueEvent = function (name, callback) {
3784 getOrSetAsInMap(this._queuedCallbacks, name, []).push(callback);
3785 };
3786 TransitionAnimationPlayer.prototype.onDone = function (fn) {
3787 if (this.queued) {
3788 this._queueEvent('done', fn);
3789 }
3790 this._player.onDone(fn);
3791 };
3792 TransitionAnimationPlayer.prototype.onStart = function (fn) {
3793 if (this.queued) {
3794 this._queueEvent('start', fn);
3795 }
3796 this._player.onStart(fn);
3797 };
3798 TransitionAnimationPlayer.prototype.onDestroy = function (fn) {
3799 if (this.queued) {
3800 this._queueEvent('destroy', fn);
3801 }
3802 this._player.onDestroy(fn);
3803 };
3804 TransitionAnimationPlayer.prototype.init = function () { this._player.init(); };
3805 TransitionAnimationPlayer.prototype.hasStarted = function () { return this.queued ? false : this._player.hasStarted(); };
3806 TransitionAnimationPlayer.prototype.play = function () { !this.queued && this._player.play(); };
3807 TransitionAnimationPlayer.prototype.pause = function () { !this.queued && this._player.pause(); };
3808 TransitionAnimationPlayer.prototype.restart = function () { !this.queued && this._player.restart(); };
3809 TransitionAnimationPlayer.prototype.finish = function () { this._player.finish(); };
3810 TransitionAnimationPlayer.prototype.destroy = function () {
3811 this.destroyed = true;
3812 this._player.destroy();
3813 };
3814 TransitionAnimationPlayer.prototype.reset = function () { !this.queued && this._player.reset(); };
3815 TransitionAnimationPlayer.prototype.setPosition = function (p) {
3816 if (!this.queued) {
3817 this._player.setPosition(p);
3818 }
3819 };
3820 TransitionAnimationPlayer.prototype.getPosition = function () { return this.queued ? 0 : this._player.getPosition(); };
3821 /** @internal */
3822 TransitionAnimationPlayer.prototype.triggerCallback = function (phaseName) {
3823 var p = this._player;
3824 if (p.triggerCallback) {
3825 p.triggerCallback(phaseName);
3826 }
3827 };
3828 return TransitionAnimationPlayer;
3829 }());
3830 function deleteOrUnsetInMap(map, key, value) {
3831 var currentValues;
3832 if (map instanceof Map) {
3833 currentValues = map.get(key);
3834 if (currentValues) {
3835 if (currentValues.length) {
3836 var index = currentValues.indexOf(value);
3837 currentValues.splice(index, 1);
3838 }
3839 if (currentValues.length == 0) {
3840 map.delete(key);
3841 }
3842 }
3843 }
3844 else {
3845 currentValues = map[key];
3846 if (currentValues) {
3847 if (currentValues.length) {
3848 var index = currentValues.indexOf(value);
3849 currentValues.splice(index, 1);
3850 }
3851 if (currentValues.length == 0) {
3852 delete map[key];
3853 }
3854 }
3855 }
3856 return currentValues;
3857 }
3858 function normalizeTriggerValue(value) {
3859 // we use `!= null` here because it's the most simple
3860 // way to test against a "falsy" value without mixing
3861 // in empty strings or a zero value. DO NOT OPTIMIZE.
3862 return value != null ? value : null;
3863 }
3864 function isElementNode(node) {
3865 return node && node['nodeType'] === 1;
3866 }
3867 function isTriggerEventValid(eventName) {
3868 return eventName == 'start' || eventName == 'done';
3869 }
3870 function cloakElement(element, value) {
3871 var oldValue = element.style.display;
3872 element.style.display = value != null ? value : 'none';
3873 return oldValue;
3874 }
3875 function cloakAndComputeStyles(valuesMap, driver, elements, elementPropsMap, defaultStyle) {
3876 var cloakVals = [];
3877 elements.forEach(function (element) { return cloakVals.push(cloakElement(element)); });
3878 var failedElements = [];
3879 elementPropsMap.forEach(function (props, element) {
3880 var styles = {};
3881 props.forEach(function (prop) {
3882 var value = styles[prop] = driver.computeStyle(element, prop, defaultStyle);
3883 // there is no easy way to detect this because a sub element could be removed
3884 // by a parent animation element being detached.
3885 if (!value || value.length == 0) {
3886 element[REMOVAL_FLAG] = NULL_REMOVED_QUERIED_STATE;
3887 failedElements.push(element);
3888 }
3889 });
3890 valuesMap.set(element, styles);
3891 });
3892 // we use a index variable here since Set.forEach(a, i) does not return
3893 // an index value for the closure (but instead just the value)
3894 var i = 0;
3895 elements.forEach(function (element) { return cloakElement(element, cloakVals[i++]); });
3896 return failedElements;
3897 }
3898 /*
3899 Since the Angular renderer code will return a collection of inserted
3900 nodes in all areas of a DOM tree, it's up to this algorithm to figure
3901 out which nodes are roots for each animation @trigger.
3902
3903 By placing each inserted node into a Set and traversing upwards, it
3904 is possible to find the @trigger elements and well any direct *star
3905 insertion nodes, if a @trigger root is found then the enter element
3906 is placed into the Map[@trigger] spot.
3907 */
3908 function buildRootMap(roots, nodes) {
3909 var rootMap = new Map();
3910 roots.forEach(function (root) { return rootMap.set(root, []); });
3911 if (nodes.length == 0)
3912 return rootMap;
3913 var NULL_NODE = 1;
3914 var nodeSet = new Set(nodes);
3915 var localRootMap = new Map();
3916 function getRoot(node) {
3917 if (!node)
3918 return NULL_NODE;
3919 var root = localRootMap.get(node);
3920 if (root)
3921 return root;
3922 var parent = node.parentNode;
3923 if (rootMap.has(parent)) { // ngIf inside @trigger
3924 root = parent;
3925 }
3926 else if (nodeSet.has(parent)) { // ngIf inside ngIf
3927 root = NULL_NODE;
3928 }
3929 else { // recurse upwards
3930 root = getRoot(parent);
3931 }
3932 localRootMap.set(node, root);
3933 return root;
3934 }
3935 nodes.forEach(function (node) {
3936 var root = getRoot(node);
3937 if (root !== NULL_NODE) {
3938 rootMap.get(root).push(node);
3939 }
3940 });
3941 return rootMap;
3942 }
3943 var CLASSES_CACHE_KEY = '$$classes';
3944 function containsClass(element, className) {
3945 if (element.classList) {
3946 return element.classList.contains(className);
3947 }
3948 else {
3949 var classes = element[CLASSES_CACHE_KEY];
3950 return classes && classes[className];
3951 }
3952 }
3953 function addClass(element, className) {
3954 if (element.classList) {
3955 element.classList.add(className);
3956 }
3957 else {
3958 var classes = element[CLASSES_CACHE_KEY];
3959 if (!classes) {
3960 classes = element[CLASSES_CACHE_KEY] = {};
3961 }
3962 classes[className] = true;
3963 }
3964 }
3965 function removeClass(element, className) {
3966 if (element.classList) {
3967 element.classList.remove(className);
3968 }
3969 else {
3970 var classes = element[CLASSES_CACHE_KEY];
3971 if (classes) {
3972 delete classes[className];
3973 }
3974 }
3975 }
3976 function removeNodesAfterAnimationDone(engine, element, players) {
3977 optimizeGroupPlayer(players).onDone(function () { return engine.processLeaveNode(element); });
3978 }
3979 function flattenGroupPlayers(players) {
3980 var finalPlayers = [];
3981 _flattenGroupPlayersRecur(players, finalPlayers);
3982 return finalPlayers;
3983 }
3984 function _flattenGroupPlayersRecur(players, finalPlayers) {
3985 for (var i = 0; i < players.length; i++) {
3986 var player = players[i];
3987 if (player instanceof animations.ɵAnimationGroupPlayer) {
3988 _flattenGroupPlayersRecur(player.players, finalPlayers);
3989 }
3990 else {
3991 finalPlayers.push(player);
3992 }
3993 }
3994 }
3995 function objEquals(a, b) {
3996 var k1 = Object.keys(a);
3997 var k2 = Object.keys(b);
3998 if (k1.length != k2.length)
3999 return false;
4000 for (var i = 0; i < k1.length; i++) {
4001 var prop = k1[i];
4002 if (!b.hasOwnProperty(prop) || a[prop] !== b[prop])
4003 return false;
4004 }
4005 return true;
4006 }
4007 function replacePostStylesAsPre(element, allPreStyleElements, allPostStyleElements) {
4008 var postEntry = allPostStyleElements.get(element);
4009 if (!postEntry)
4010 return false;
4011 var preEntry = allPreStyleElements.get(element);
4012 if (preEntry) {
4013 postEntry.forEach(function (data) { return preEntry.add(data); });
4014 }
4015 else {
4016 allPreStyleElements.set(element, postEntry);
4017 }
4018 allPostStyleElements.delete(element);
4019 return true;
4020 }
4021
4022 var AnimationEngine = /** @class */ (function () {
4023 function AnimationEngine(bodyNode, _driver, normalizer) {
4024 var _this = this;
4025 this.bodyNode = bodyNode;
4026 this._driver = _driver;
4027 this._triggerCache = {};
4028 // this method is designed to be overridden by the code that uses this engine
4029 this.onRemovalComplete = function (element, context) { };
4030 this._transitionEngine = new TransitionAnimationEngine(bodyNode, _driver, normalizer);
4031 this._timelineEngine = new TimelineAnimationEngine(bodyNode, _driver, normalizer);
4032 this._transitionEngine.onRemovalComplete = function (element, context) {
4033 return _this.onRemovalComplete(element, context);
4034 };
4035 }
4036 AnimationEngine.prototype.registerTrigger = function (componentId, namespaceId, hostElement, name, metadata) {
4037 var cacheKey = componentId + '-' + name;
4038 var trigger = this._triggerCache[cacheKey];
4039 if (!trigger) {
4040 var errors = [];
4041 var ast = buildAnimationAst(this._driver, metadata, errors);
4042 if (errors.length) {
4043 throw new Error("The animation trigger \"" + name + "\" has failed to build due to the following errors:\n - " + errors.join("\n - "));
4044 }
4045 trigger = buildTrigger(name, ast);
4046 this._triggerCache[cacheKey] = trigger;
4047 }
4048 this._transitionEngine.registerTrigger(namespaceId, name, trigger);
4049 };
4050 AnimationEngine.prototype.register = function (namespaceId, hostElement) {
4051 this._transitionEngine.register(namespaceId, hostElement);
4052 };
4053 AnimationEngine.prototype.destroy = function (namespaceId, context) {
4054 this._transitionEngine.destroy(namespaceId, context);
4055 };
4056 AnimationEngine.prototype.onInsert = function (namespaceId, element, parent, insertBefore) {
4057 this._transitionEngine.insertNode(namespaceId, element, parent, insertBefore);
4058 };
4059 AnimationEngine.prototype.onRemove = function (namespaceId, element, context, isHostElement) {
4060 this._transitionEngine.removeNode(namespaceId, element, isHostElement || false, context);
4061 };
4062 AnimationEngine.prototype.disableAnimations = function (element, disable) {
4063 this._transitionEngine.markElementAsDisabled(element, disable);
4064 };
4065 AnimationEngine.prototype.process = function (namespaceId, element, property, value) {
4066 if (property.charAt(0) == '@') {
4067 var _a = __read(parseTimelineCommand(property), 2), id = _a[0], action = _a[1];
4068 var args = value;
4069 this._timelineEngine.command(id, element, action, args);
4070 }
4071 else {
4072 this._transitionEngine.trigger(namespaceId, element, property, value);
4073 }
4074 };
4075 AnimationEngine.prototype.listen = function (namespaceId, element, eventName, eventPhase, callback) {
4076 // @@listen
4077 if (eventName.charAt(0) == '@') {
4078 var _a = __read(parseTimelineCommand(eventName), 2), id = _a[0], action = _a[1];
4079 return this._timelineEngine.listen(id, element, action, callback);
4080 }
4081 return this._transitionEngine.listen(namespaceId, element, eventName, eventPhase, callback);
4082 };
4083 AnimationEngine.prototype.flush = function (microtaskId) {
4084 if (microtaskId === void 0) { microtaskId = -1; }
4085 this._transitionEngine.flush(microtaskId);
4086 };
4087 Object.defineProperty(AnimationEngine.prototype, "players", {
4088 get: function () {
4089 return this._transitionEngine.players
4090 .concat(this._timelineEngine.players);
4091 },
4092 enumerable: true,
4093 configurable: true
4094 });
4095 AnimationEngine.prototype.whenRenderingDone = function () { return this._transitionEngine.whenRenderingDone(); };
4096 return AnimationEngine;
4097 }());
4098
4099 /**
4100 * @license
4101 * Copyright Google Inc. All Rights Reserved.
4102 *
4103 * Use of this source code is governed by an MIT-style license that can be
4104 * found in the LICENSE file at https://angular.io/license
4105 */
4106 /**
4107 * Returns an instance of `SpecialCasedStyles` if and when any special (non animateable) styles are
4108 * detected.
4109 *
4110 * In CSS there exist properties that cannot be animated within a keyframe animation
4111 * (whether it be via CSS keyframes or web-animations) and the animation implementation
4112 * will ignore them. This function is designed to detect those special cased styles and
4113 * return a container that will be executed at the start and end of the animation.
4114 *
4115 * @returns an instance of `SpecialCasedStyles` if any special styles are detected otherwise `null`
4116 */
4117 function packageNonAnimatableStyles(element, styles) {
4118 var startStyles = null;
4119 var endStyles = null;
4120 if (Array.isArray(styles) && styles.length) {
4121 startStyles = filterNonAnimatableStyles(styles[0]);
4122 if (styles.length > 1) {
4123 endStyles = filterNonAnimatableStyles(styles[styles.length - 1]);
4124 }
4125 }
4126 else if (styles) {
4127 startStyles = filterNonAnimatableStyles(styles);
4128 }
4129 return (startStyles || endStyles) ? new SpecialCasedStyles(element, startStyles, endStyles) :
4130 null;
4131 }
4132 /**
4133 * Designed to be executed during a keyframe-based animation to apply any special-cased styles.
4134 *
4135 * When started (when the `start()` method is run) then the provided `startStyles`
4136 * will be applied. When finished (when the `finish()` method is called) the
4137 * `endStyles` will be applied as well any any starting styles. Finally when
4138 * `destroy()` is called then all styles will be removed.
4139 */
4140 var SpecialCasedStyles = /** @class */ (function () {
4141 function SpecialCasedStyles(_element, _startStyles, _endStyles) {
4142 this._element = _element;
4143 this._startStyles = _startStyles;
4144 this._endStyles = _endStyles;
4145 this._state = 0 /* Pending */;
4146 var initialStyles = SpecialCasedStyles.initialStylesByElement.get(_element);
4147 if (!initialStyles) {
4148 SpecialCasedStyles.initialStylesByElement.set(_element, initialStyles = {});
4149 }
4150 this._initialStyles = initialStyles;
4151 }
4152 SpecialCasedStyles.prototype.start = function () {
4153 if (this._state < 1 /* Started */) {
4154 if (this._startStyles) {
4155 setStyles(this._element, this._startStyles, this._initialStyles);
4156 }
4157 this._state = 1 /* Started */;
4158 }
4159 };
4160 SpecialCasedStyles.prototype.finish = function () {
4161 this.start();
4162 if (this._state < 2 /* Finished */) {
4163 setStyles(this._element, this._initialStyles);
4164 if (this._endStyles) {
4165 setStyles(this._element, this._endStyles);
4166 this._endStyles = null;
4167 }
4168 this._state = 1 /* Started */;
4169 }
4170 };
4171 SpecialCasedStyles.prototype.destroy = function () {
4172 this.finish();
4173 if (this._state < 3 /* Destroyed */) {
4174 SpecialCasedStyles.initialStylesByElement.delete(this._element);
4175 if (this._startStyles) {
4176 eraseStyles(this._element, this._startStyles);
4177 this._endStyles = null;
4178 }
4179 if (this._endStyles) {
4180 eraseStyles(this._element, this._endStyles);
4181 this._endStyles = null;
4182 }
4183 setStyles(this._element, this._initialStyles);
4184 this._state = 3 /* Destroyed */;
4185 }
4186 };
4187 SpecialCasedStyles.initialStylesByElement = new WeakMap();
4188 return SpecialCasedStyles;
4189 }());
4190 function filterNonAnimatableStyles(styles) {
4191 var result = null;
4192 var props = Object.keys(styles);
4193 for (var i = 0; i < props.length; i++) {
4194 var prop = props[i];
4195 if (isNonAnimatableStyle(prop)) {
4196 result = result || {};
4197 result[prop] = styles[prop];
4198 }
4199 }
4200 return result;
4201 }
4202 function isNonAnimatableStyle(prop) {
4203 return prop === 'display' || prop === 'position';
4204 }
4205
4206 /**
4207 * @license
4208 * Copyright Google Inc. All Rights Reserved.
4209 *
4210 * Use of this source code is governed by an MIT-style license that can be
4211 * found in the LICENSE file at https://angular.io/license
4212 */
4213 var ELAPSED_TIME_MAX_DECIMAL_PLACES = 3;
4214 var ANIMATION_PROP = 'animation';
4215 var ANIMATIONEND_EVENT = 'animationend';
4216 var ONE_SECOND$1 = 1000;
4217 var ElementAnimationStyleHandler = /** @class */ (function () {
4218 function ElementAnimationStyleHandler(_element, _name, _duration, _delay, _easing, _fillMode, _onDoneFn) {
4219 var _this = this;
4220 this._element = _element;
4221 this._name = _name;
4222 this._duration = _duration;
4223 this._delay = _delay;
4224 this._easing = _easing;
4225 this._fillMode = _fillMode;
4226 this._onDoneFn = _onDoneFn;
4227 this._finished = false;
4228 this._destroyed = false;
4229 this._startTime = 0;
4230 this._position = 0;
4231 this._eventFn = function (e) { return _this._handleCallback(e); };
4232 }
4233 ElementAnimationStyleHandler.prototype.apply = function () {
4234 applyKeyframeAnimation(this._element, this._duration + "ms " + this._easing + " " + this._delay + "ms 1 normal " + this._fillMode + " " + this._name);
4235 addRemoveAnimationEvent(this._element, this._eventFn, false);
4236 this._startTime = Date.now();
4237 };
4238 ElementAnimationStyleHandler.prototype.pause = function () { playPauseAnimation(this._element, this._name, 'paused'); };
4239 ElementAnimationStyleHandler.prototype.resume = function () { playPauseAnimation(this._element, this._name, 'running'); };
4240 ElementAnimationStyleHandler.prototype.setPosition = function (position) {
4241 var index = findIndexForAnimation(this._element, this._name);
4242 this._position = position * this._duration;
4243 setAnimationStyle(this._element, 'Delay', "-" + this._position + "ms", index);
4244 };
4245 ElementAnimationStyleHandler.prototype.getPosition = function () { return this._position; };
4246 ElementAnimationStyleHandler.prototype._handleCallback = function (event) {
4247 var timestamp = event._ngTestManualTimestamp || Date.now();
4248 var elapsedTime = parseFloat(event.elapsedTime.toFixed(ELAPSED_TIME_MAX_DECIMAL_PLACES)) * ONE_SECOND$1;
4249 if (event.animationName == this._name &&
4250 Math.max(timestamp - this._startTime, 0) >= this._delay && elapsedTime >= this._duration) {
4251 this.finish();
4252 }
4253 };
4254 ElementAnimationStyleHandler.prototype.finish = function () {
4255 if (this._finished)
4256 return;
4257 this._finished = true;
4258 this._onDoneFn();
4259 addRemoveAnimationEvent(this._element, this._eventFn, true);
4260 };
4261 ElementAnimationStyleHandler.prototype.destroy = function () {
4262 if (this._destroyed)
4263 return;
4264 this._destroyed = true;
4265 this.finish();
4266 removeKeyframeAnimation(this._element, this._name);
4267 };
4268 return ElementAnimationStyleHandler;
4269 }());
4270 function playPauseAnimation(element, name, status) {
4271 var index = findIndexForAnimation(element, name);
4272 setAnimationStyle(element, 'PlayState', status, index);
4273 }
4274 function applyKeyframeAnimation(element, value) {
4275 var anim = getAnimationStyle(element, '').trim();
4276 var index = 0;
4277 if (anim.length) {
4278 index = countChars(anim, ',') + 1;
4279 value = anim + ", " + value;
4280 }
4281 setAnimationStyle(element, '', value);
4282 return index;
4283 }
4284 function removeKeyframeAnimation(element, name) {
4285 var anim = getAnimationStyle(element, '');
4286 var tokens = anim.split(',');
4287 var index = findMatchingTokenIndex(tokens, name);
4288 if (index >= 0) {
4289 tokens.splice(index, 1);
4290 var newValue = tokens.join(',');
4291 setAnimationStyle(element, '', newValue);
4292 }
4293 }
4294 function findIndexForAnimation(element, value) {
4295 var anim = getAnimationStyle(element, '');
4296 if (anim.indexOf(',') > 0) {
4297 var tokens = anim.split(',');
4298 return findMatchingTokenIndex(tokens, value);
4299 }
4300 return findMatchingTokenIndex([anim], value);
4301 }
4302 function findMatchingTokenIndex(tokens, searchToken) {
4303 for (var i = 0; i < tokens.length; i++) {
4304 if (tokens[i].indexOf(searchToken) >= 0) {
4305 return i;
4306 }
4307 }
4308 return -1;
4309 }
4310 function addRemoveAnimationEvent(element, fn, doRemove) {
4311 doRemove ? element.removeEventListener(ANIMATIONEND_EVENT, fn) :
4312 element.addEventListener(ANIMATIONEND_EVENT, fn);
4313 }
4314 function setAnimationStyle(element, name, value, index) {
4315 var prop = ANIMATION_PROP + name;
4316 if (index != null) {
4317 var oldValue = element.style[prop];
4318 if (oldValue.length) {
4319 var tokens = oldValue.split(',');
4320 tokens[index] = value;
4321 value = tokens.join(',');
4322 }
4323 }
4324 element.style[prop] = value;
4325 }
4326 function getAnimationStyle(element, name) {
4327 return element.style[ANIMATION_PROP + name];
4328 }
4329 function countChars(value, char) {
4330 var count = 0;
4331 for (var i = 0; i < value.length; i++) {
4332 var c = value.charAt(i);
4333 if (c === char)
4334 count++;
4335 }
4336 return count;
4337 }
4338
4339 var DEFAULT_FILL_MODE = 'forwards';
4340 var DEFAULT_EASING = 'linear';
4341 var CssKeyframesPlayer = /** @class */ (function () {
4342 function CssKeyframesPlayer(element, keyframes, animationName, _duration, _delay, easing, _finalStyles, _specialStyles) {
4343 this.element = element;
4344 this.keyframes = keyframes;
4345 this.animationName = animationName;
4346 this._duration = _duration;
4347 this._delay = _delay;
4348 this._finalStyles = _finalStyles;
4349 this._specialStyles = _specialStyles;
4350 this._onDoneFns = [];
4351 this._onStartFns = [];
4352 this._onDestroyFns = [];
4353 this._started = false;
4354 this.currentSnapshot = {};
4355 this._state = 0;
4356 this.easing = easing || DEFAULT_EASING;
4357 this.totalTime = _duration + _delay;
4358 this._buildStyler();
4359 }
4360 CssKeyframesPlayer.prototype.onStart = function (fn) { this._onStartFns.push(fn); };
4361 CssKeyframesPlayer.prototype.onDone = function (fn) { this._onDoneFns.push(fn); };
4362 CssKeyframesPlayer.prototype.onDestroy = function (fn) { this._onDestroyFns.push(fn); };
4363 CssKeyframesPlayer.prototype.destroy = function () {
4364 this.init();
4365 if (this._state >= 4 /* DESTROYED */)
4366 return;
4367 this._state = 4 /* DESTROYED */;
4368 this._styler.destroy();
4369 this._flushStartFns();
4370 this._flushDoneFns();
4371 if (this._specialStyles) {
4372 this._specialStyles.destroy();
4373 }
4374 this._onDestroyFns.forEach(function (fn) { return fn(); });
4375 this._onDestroyFns = [];
4376 };
4377 CssKeyframesPlayer.prototype._flushDoneFns = function () {
4378 this._onDoneFns.forEach(function (fn) { return fn(); });
4379 this._onDoneFns = [];
4380 };
4381 CssKeyframesPlayer.prototype._flushStartFns = function () {
4382 this._onStartFns.forEach(function (fn) { return fn(); });
4383 this._onStartFns = [];
4384 };
4385 CssKeyframesPlayer.prototype.finish = function () {
4386 this.init();
4387 if (this._state >= 3 /* FINISHED */)
4388 return;
4389 this._state = 3 /* FINISHED */;
4390 this._styler.finish();
4391 this._flushStartFns();
4392 if (this._specialStyles) {
4393 this._specialStyles.finish();
4394 }
4395 this._flushDoneFns();
4396 };
4397 CssKeyframesPlayer.prototype.setPosition = function (value) { this._styler.setPosition(value); };
4398 CssKeyframesPlayer.prototype.getPosition = function () { return this._styler.getPosition(); };
4399 CssKeyframesPlayer.prototype.hasStarted = function () { return this._state >= 2 /* STARTED */; };
4400 CssKeyframesPlayer.prototype.init = function () {
4401 if (this._state >= 1 /* INITIALIZED */)
4402 return;
4403 this._state = 1 /* INITIALIZED */;
4404 var elm = this.element;
4405 this._styler.apply();
4406 if (this._delay) {
4407 this._styler.pause();
4408 }
4409 };
4410 CssKeyframesPlayer.prototype.play = function () {
4411 this.init();
4412 if (!this.hasStarted()) {
4413 this._flushStartFns();
4414 this._state = 2 /* STARTED */;
4415 if (this._specialStyles) {
4416 this._specialStyles.start();
4417 }
4418 }
4419 this._styler.resume();
4420 };
4421 CssKeyframesPlayer.prototype.pause = function () {
4422 this.init();
4423 this._styler.pause();
4424 };
4425 CssKeyframesPlayer.prototype.restart = function () {
4426 this.reset();
4427 this.play();
4428 };
4429 CssKeyframesPlayer.prototype.reset = function () {
4430 this._styler.destroy();
4431 this._buildStyler();
4432 this._styler.apply();
4433 };
4434 CssKeyframesPlayer.prototype._buildStyler = function () {
4435 var _this = this;
4436 this._styler = new ElementAnimationStyleHandler(this.element, this.animationName, this._duration, this._delay, this.easing, DEFAULT_FILL_MODE, function () { return _this.finish(); });
4437 };
4438 /** @internal */
4439 CssKeyframesPlayer.prototype.triggerCallback = function (phaseName) {
4440 var methods = phaseName == 'start' ? this._onStartFns : this._onDoneFns;
4441 methods.forEach(function (fn) { return fn(); });
4442 methods.length = 0;
4443 };
4444 CssKeyframesPlayer.prototype.beforeDestroy = function () {
4445 var _this = this;
4446 this.init();
4447 var styles = {};
4448 if (this.hasStarted()) {
4449 var finished_1 = this._state >= 3 /* FINISHED */;
4450 Object.keys(this._finalStyles).forEach(function (prop) {
4451 if (prop != 'offset') {
4452 styles[prop] = finished_1 ? _this._finalStyles[prop] : computeStyle(_this.element, prop);
4453 }
4454 });
4455 }
4456 this.currentSnapshot = styles;
4457 };
4458 return CssKeyframesPlayer;
4459 }());
4460
4461 var DirectStylePlayer = /** @class */ (function (_super) {
4462 __extends(DirectStylePlayer, _super);
4463 function DirectStylePlayer(element, styles) {
4464 var _this = _super.call(this) || this;
4465 _this.element = element;
4466 _this._startingStyles = {};
4467 _this.__initialized = false;
4468 _this._styles = hypenatePropsObject(styles);
4469 return _this;
4470 }
4471 DirectStylePlayer.prototype.init = function () {
4472 var _this = this;
4473 if (this.__initialized || !this._startingStyles)
4474 return;
4475 this.__initialized = true;
4476 Object.keys(this._styles).forEach(function (prop) {
4477 _this._startingStyles[prop] = _this.element.style[prop];
4478 });
4479 _super.prototype.init.call(this);
4480 };
4481 DirectStylePlayer.prototype.play = function () {
4482 var _this = this;
4483 if (!this._startingStyles)
4484 return;
4485 this.init();
4486 Object.keys(this._styles)
4487 .forEach(function (prop) { return _this.element.style.setProperty(prop, _this._styles[prop]); });
4488 _super.prototype.play.call(this);
4489 };
4490 DirectStylePlayer.prototype.destroy = function () {
4491 var _this = this;
4492 if (!this._startingStyles)
4493 return;
4494 Object.keys(this._startingStyles).forEach(function (prop) {
4495 var value = _this._startingStyles[prop];
4496 if (value) {
4497 _this.element.style.setProperty(prop, value);
4498 }
4499 else {
4500 _this.element.style.removeProperty(prop);
4501 }
4502 });
4503 this._startingStyles = null;
4504 _super.prototype.destroy.call(this);
4505 };
4506 return DirectStylePlayer;
4507 }(animations.NoopAnimationPlayer));
4508
4509 var KEYFRAMES_NAME_PREFIX = 'gen_css_kf_';
4510 var TAB_SPACE = ' ';
4511 var CssKeyframesDriver = /** @class */ (function () {
4512 function CssKeyframesDriver() {
4513 this._count = 0;
4514 this._head = document.querySelector('head');
4515 this._warningIssued = false;
4516 }
4517 CssKeyframesDriver.prototype.validateStyleProperty = function (prop) { return validateStyleProperty(prop); };
4518 CssKeyframesDriver.prototype.matchesElement = function (element, selector) {
4519 return matchesElement(element, selector);
4520 };
4521 CssKeyframesDriver.prototype.containsElement = function (elm1, elm2) { return containsElement(elm1, elm2); };
4522 CssKeyframesDriver.prototype.query = function (element, selector, multi) {
4523 return invokeQuery(element, selector, multi);
4524 };
4525 CssKeyframesDriver.prototype.computeStyle = function (element, prop, defaultValue) {
4526 return window.getComputedStyle(element)[prop];
4527 };
4528 CssKeyframesDriver.prototype.buildKeyframeElement = function (element, name, keyframes) {
4529 keyframes = keyframes.map(function (kf) { return hypenatePropsObject(kf); });
4530 var keyframeStr = "@keyframes " + name + " {\n";
4531 var tab = '';
4532 keyframes.forEach(function (kf) {
4533 tab = TAB_SPACE;
4534 var offset = parseFloat(kf['offset']);
4535 keyframeStr += "" + tab + offset * 100 + "% {\n";
4536 tab += TAB_SPACE;
4537 Object.keys(kf).forEach(function (prop) {
4538 var value = kf[prop];
4539 switch (prop) {
4540 case 'offset':
4541 return;
4542 case 'easing':
4543 if (value) {
4544 keyframeStr += tab + "animation-timing-function: " + value + ";\n";
4545 }
4546 return;
4547 default:
4548 keyframeStr += "" + tab + prop + ": " + value + ";\n";
4549 return;
4550 }
4551 });
4552 keyframeStr += tab + "}\n";
4553 });
4554 keyframeStr += "}\n";
4555 var kfElm = document.createElement('style');
4556 kfElm.innerHTML = keyframeStr;
4557 return kfElm;
4558 };
4559 CssKeyframesDriver.prototype.animate = function (element, keyframes, duration, delay, easing, previousPlayers, scrubberAccessRequested) {
4560 if (previousPlayers === void 0) { previousPlayers = []; }
4561 if (scrubberAccessRequested) {
4562 this._notifyFaultyScrubber();
4563 }
4564 var previousCssKeyframePlayers = previousPlayers.filter(function (player) { return player instanceof CssKeyframesPlayer; });
4565 var previousStyles = {};
4566 if (allowPreviousPlayerStylesMerge(duration, delay)) {
4567 previousCssKeyframePlayers.forEach(function (player) {
4568 var styles = player.currentSnapshot;
4569 Object.keys(styles).forEach(function (prop) { return previousStyles[prop] = styles[prop]; });
4570 });
4571 }
4572 keyframes = balancePreviousStylesIntoKeyframes(element, keyframes, previousStyles);
4573 var finalStyles = flattenKeyframesIntoStyles(keyframes);
4574 // if there is no animation then there is no point in applying
4575 // styles and waiting for an event to get fired. This causes lag.
4576 // It's better to just directly apply the styles to the element
4577 // via the direct styling animation player.
4578 if (duration == 0) {
4579 return new DirectStylePlayer(element, finalStyles);
4580 }
4581 var animationName = "" + KEYFRAMES_NAME_PREFIX + this._count++;
4582 var kfElm = this.buildKeyframeElement(element, animationName, keyframes);
4583 document.querySelector('head').appendChild(kfElm);
4584 var specialStyles = packageNonAnimatableStyles(element, keyframes);
4585 var player = new CssKeyframesPlayer(element, keyframes, animationName, duration, delay, easing, finalStyles, specialStyles);
4586 player.onDestroy(function () { return removeElement(kfElm); });
4587 return player;
4588 };
4589 CssKeyframesDriver.prototype._notifyFaultyScrubber = function () {
4590 if (!this._warningIssued) {
4591 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.');
4592 this._warningIssued = true;
4593 }
4594 };
4595 return CssKeyframesDriver;
4596 }());
4597 function flattenKeyframesIntoStyles(keyframes) {
4598 var flatKeyframes = {};
4599 if (keyframes) {
4600 var kfs = Array.isArray(keyframes) ? keyframes : [keyframes];
4601 kfs.forEach(function (kf) {
4602 Object.keys(kf).forEach(function (prop) {
4603 if (prop == 'offset' || prop == 'easing')
4604 return;
4605 flatKeyframes[prop] = kf[prop];
4606 });
4607 });
4608 }
4609 return flatKeyframes;
4610 }
4611 function removeElement(node) {
4612 node.parentNode.removeChild(node);
4613 }
4614
4615 var WebAnimationsPlayer = /** @class */ (function () {
4616 function WebAnimationsPlayer(element, keyframes, options, _specialStyles) {
4617 this.element = element;
4618 this.keyframes = keyframes;
4619 this.options = options;
4620 this._specialStyles = _specialStyles;
4621 this._onDoneFns = [];
4622 this._onStartFns = [];
4623 this._onDestroyFns = [];
4624 this._initialized = false;
4625 this._finished = false;
4626 this._started = false;
4627 this._destroyed = false;
4628 this.time = 0;
4629 this.parentPlayer = null;
4630 this.currentSnapshot = {};
4631 this._duration = options['duration'];
4632 this._delay = options['delay'] || 0;
4633 this.time = this._duration + this._delay;
4634 }
4635 WebAnimationsPlayer.prototype._onFinish = function () {
4636 if (!this._finished) {
4637 this._finished = true;
4638 this._onDoneFns.forEach(function (fn) { return fn(); });
4639 this._onDoneFns = [];
4640 }
4641 };
4642 WebAnimationsPlayer.prototype.init = function () {
4643 this._buildPlayer();
4644 this._preparePlayerBeforeStart();
4645 };
4646 WebAnimationsPlayer.prototype._buildPlayer = function () {
4647 var _this = this;
4648 if (this._initialized)
4649 return;
4650 this._initialized = true;
4651 var keyframes = this.keyframes;
4652 this.domPlayer =
4653 this._triggerWebAnimation(this.element, keyframes, this.options);
4654 this._finalKeyframe = keyframes.length ? keyframes[keyframes.length - 1] : {};
4655 this.domPlayer.addEventListener('finish', function () { return _this._onFinish(); });
4656 };
4657 WebAnimationsPlayer.prototype._preparePlayerBeforeStart = function () {
4658 // this is required so that the player doesn't start to animate right away
4659 if (this._delay) {
4660 this._resetDomPlayerState();
4661 }
4662 else {
4663 this.domPlayer.pause();
4664 }
4665 };
4666 /** @internal */
4667 WebAnimationsPlayer.prototype._triggerWebAnimation = function (element, keyframes, options) {
4668 // jscompiler doesn't seem to know animate is a native property because it's not fully
4669 // supported yet across common browsers (we polyfill it for Edge/Safari) [CL #143630929]
4670 return element['animate'](keyframes, options);
4671 };
4672 WebAnimationsPlayer.prototype.onStart = function (fn) { this._onStartFns.push(fn); };
4673 WebAnimationsPlayer.prototype.onDone = function (fn) { this._onDoneFns.push(fn); };
4674 WebAnimationsPlayer.prototype.onDestroy = function (fn) { this._onDestroyFns.push(fn); };
4675 WebAnimationsPlayer.prototype.play = function () {
4676 this._buildPlayer();
4677 if (!this.hasStarted()) {
4678 this._onStartFns.forEach(function (fn) { return fn(); });
4679 this._onStartFns = [];
4680 this._started = true;
4681 if (this._specialStyles) {
4682 this._specialStyles.start();
4683 }
4684 }
4685 this.domPlayer.play();
4686 };
4687 WebAnimationsPlayer.prototype.pause = function () {
4688 this.init();
4689 this.domPlayer.pause();
4690 };
4691 WebAnimationsPlayer.prototype.finish = function () {
4692 this.init();
4693 if (this._specialStyles) {
4694 this._specialStyles.finish();
4695 }
4696 this._onFinish();
4697 this.domPlayer.finish();
4698 };
4699 WebAnimationsPlayer.prototype.reset = function () {
4700 this._resetDomPlayerState();
4701 this._destroyed = false;
4702 this._finished = false;
4703 this._started = false;
4704 };
4705 WebAnimationsPlayer.prototype._resetDomPlayerState = function () {
4706 if (this.domPlayer) {
4707 this.domPlayer.cancel();
4708 }
4709 };
4710 WebAnimationsPlayer.prototype.restart = function () {
4711 this.reset();
4712 this.play();
4713 };
4714 WebAnimationsPlayer.prototype.hasStarted = function () { return this._started; };
4715 WebAnimationsPlayer.prototype.destroy = function () {
4716 if (!this._destroyed) {
4717 this._destroyed = true;
4718 this._resetDomPlayerState();
4719 this._onFinish();
4720 if (this._specialStyles) {
4721 this._specialStyles.destroy();
4722 }
4723 this._onDestroyFns.forEach(function (fn) { return fn(); });
4724 this._onDestroyFns = [];
4725 }
4726 };
4727 WebAnimationsPlayer.prototype.setPosition = function (p) { this.domPlayer.currentTime = p * this.time; };
4728 WebAnimationsPlayer.prototype.getPosition = function () { return this.domPlayer.currentTime / this.time; };
4729 Object.defineProperty(WebAnimationsPlayer.prototype, "totalTime", {
4730 get: function () { return this._delay + this._duration; },
4731 enumerable: true,
4732 configurable: true
4733 });
4734 WebAnimationsPlayer.prototype.beforeDestroy = function () {
4735 var _this = this;
4736 var styles = {};
4737 if (this.hasStarted()) {
4738 Object.keys(this._finalKeyframe).forEach(function (prop) {
4739 if (prop != 'offset') {
4740 styles[prop] =
4741 _this._finished ? _this._finalKeyframe[prop] : computeStyle(_this.element, prop);
4742 }
4743 });
4744 }
4745 this.currentSnapshot = styles;
4746 };
4747 /** @internal */
4748 WebAnimationsPlayer.prototype.triggerCallback = function (phaseName) {
4749 var methods = phaseName == 'start' ? this._onStartFns : this._onDoneFns;
4750 methods.forEach(function (fn) { return fn(); });
4751 methods.length = 0;
4752 };
4753 return WebAnimationsPlayer;
4754 }());
4755
4756 var WebAnimationsDriver = /** @class */ (function () {
4757 function WebAnimationsDriver() {
4758 this._isNativeImpl = /\{\s*\[native\s+code\]\s*\}/.test(getElementAnimateFn().toString());
4759 this._cssKeyframesDriver = new CssKeyframesDriver();
4760 }
4761 WebAnimationsDriver.prototype.validateStyleProperty = function (prop) { return validateStyleProperty(prop); };
4762 WebAnimationsDriver.prototype.matchesElement = function (element, selector) {
4763 return matchesElement(element, selector);
4764 };
4765 WebAnimationsDriver.prototype.containsElement = function (elm1, elm2) { return containsElement(elm1, elm2); };
4766 WebAnimationsDriver.prototype.query = function (element, selector, multi) {
4767 return invokeQuery(element, selector, multi);
4768 };
4769 WebAnimationsDriver.prototype.computeStyle = function (element, prop, defaultValue) {
4770 return window.getComputedStyle(element)[prop];
4771 };
4772 WebAnimationsDriver.prototype.overrideWebAnimationsSupport = function (supported) { this._isNativeImpl = supported; };
4773 WebAnimationsDriver.prototype.animate = function (element, keyframes, duration, delay, easing, previousPlayers, scrubberAccessRequested) {
4774 if (previousPlayers === void 0) { previousPlayers = []; }
4775 var useKeyframes = !scrubberAccessRequested && !this._isNativeImpl;
4776 if (useKeyframes) {
4777 return this._cssKeyframesDriver.animate(element, keyframes, duration, delay, easing, previousPlayers);
4778 }
4779 var fill = delay == 0 ? 'both' : 'forwards';
4780 var playerOptions = { duration: duration, delay: delay, fill: fill };
4781 // we check for this to avoid having a null|undefined value be present
4782 // for the easing (which results in an error for certain browsers #9752)
4783 if (easing) {
4784 playerOptions['easing'] = easing;
4785 }
4786 var previousStyles = {};
4787 var previousWebAnimationPlayers = previousPlayers.filter(function (player) { return player instanceof WebAnimationsPlayer; });
4788 if (allowPreviousPlayerStylesMerge(duration, delay)) {
4789 previousWebAnimationPlayers.forEach(function (player) {
4790 var styles = player.currentSnapshot;
4791 Object.keys(styles).forEach(function (prop) { return previousStyles[prop] = styles[prop]; });
4792 });
4793 }
4794 keyframes = keyframes.map(function (styles) { return copyStyles(styles, false); });
4795 keyframes = balancePreviousStylesIntoKeyframes(element, keyframes, previousStyles);
4796 var specialStyles = packageNonAnimatableStyles(element, keyframes);
4797 return new WebAnimationsPlayer(element, keyframes, playerOptions, specialStyles);
4798 };
4799 return WebAnimationsDriver;
4800 }());
4801 function supportsWebAnimations() {
4802 return typeof getElementAnimateFn() === 'function';
4803 }
4804 function getElementAnimateFn() {
4805 return (isBrowser() && Element.prototype['animate']) || {};
4806 }
4807
4808 /**
4809 * @license
4810 * Copyright Google Inc. All Rights Reserved.
4811 *
4812 * Use of this source code is governed by an MIT-style license that can be
4813 * found in the LICENSE file at https://angular.io/license
4814 */
4815
4816 /**
4817 * @license
4818 * Copyright Google Inc. All Rights Reserved.
4819 *
4820 * Use of this source code is governed by an MIT-style license that can be
4821 * found in the LICENSE file at https://angular.io/license
4822 */
4823
4824 /**
4825 * @license
4826 * Copyright Google Inc. All Rights Reserved.
4827 *
4828 * Use of this source code is governed by an MIT-style license that can be
4829 * found in the LICENSE file at https://angular.io/license
4830 */
4831
4832 /**
4833 * @license
4834 * Copyright Google Inc. All Rights Reserved.
4835 *
4836 * Use of this source code is governed by an MIT-style license that can be
4837 * found in the LICENSE file at https://angular.io/license
4838 */
4839
4840 /**
4841 * Generated bundle index. Do not edit.
4842 */
4843
4844 exports.ɵangular_packages_animations_browser_browser_a = SpecialCasedStyles;
4845 exports.AnimationDriver = AnimationDriver;
4846 exports.ɵAnimationDriver = AnimationDriver;
4847 exports.ɵAnimation = Animation;
4848 exports.ɵAnimationStyleNormalizer = AnimationStyleNormalizer;
4849 exports.ɵNoopAnimationStyleNormalizer = NoopAnimationStyleNormalizer;
4850 exports.ɵWebAnimationsStyleNormalizer = WebAnimationsStyleNormalizer;
4851 exports.ɵNoopAnimationDriver = NoopAnimationDriver;
4852 exports.ɵAnimationEngine = AnimationEngine;
4853 exports.ɵCssKeyframesDriver = CssKeyframesDriver;
4854 exports.ɵCssKeyframesPlayer = CssKeyframesPlayer;
4855 exports.ɵcontainsElement = containsElement;
4856 exports.ɵinvokeQuery = invokeQuery;
4857 exports.ɵmatchesElement = matchesElement;
4858 exports.ɵvalidateStyleProperty = validateStyleProperty;
4859 exports.ɵWebAnimationsDriver = WebAnimationsDriver;
4860 exports.ɵsupportsWebAnimations = supportsWebAnimations;
4861 exports.ɵWebAnimationsPlayer = WebAnimationsPlayer;
4862 exports.ɵallowPreviousPlayerStylesMerge = allowPreviousPlayerStylesMerge;
4863
4864 Object.defineProperty(exports, '__esModule', { value: true });
4865
4866}));
4867//# sourceMappingURL=animations-browser.umd.js.map