browser.js 246 KB

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