UI for Zipcoin Blue

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